Skip to content

Instantly share code, notes, and snippets.

@mistakster
Last active September 6, 2020 11:55
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mistakster/3e32335655306202929d3cad3d10227f to your computer and use it in GitHub Desktop.
Save mistakster/3e32335655306202929d3cad3d10227f to your computer and use it in GitHub Desktop.
dc.js cumulative chart
(function () {
const dateFormat = d3.time.format('%Y-%m');
// produce mock data
function generateData() {
const generator = new MersenneTwister(123456);
const startDate = +new Date('2016-01-01');
const endDate = +new Date('2017-01-01');
return _.range(100)
.map(i => ({
date: new Date(generator.random() * (endDate - startDate) + startDate),
value: Math.round(generator.random() * 3000 + 100)
}));
}
/**
* Create a fake group over the original one, which provides cumulative sum
*
* @param {Object} group
* @returns {Object}
*/
function createCumulativeGroup(group) {
/**
* Aggregate ordered list to produce cumulative sum of its values
*
* @param {Array} list
* @returns {Array}
*/
function aggregate(list) {
return list.reduce((acc, item, index) => {
acc[index] = {
key: item.key,
value: item.value + (index > 0 ? acc[index - 1].value : 0)
};
return acc;
}, []);
}
// We need only limited set of methods to implement:
// all(), top(n) and dispose() are enought to draw a chart.
return {
all() {
return aggregate(group.all());
},
top(n) {
return aggregate(group.top(Infinity)).splice(0, n);
},
dispose() {
if (group.dispose) {
group.dispose();
}
}
};
}
function render(data) {
const ndx = crossfilter(data);
const dateDimension = ndx.dimension(d => dateFormat(d.date));
const dateGroup = dateDimension
.group()
.reduceSum(d => d.value);
dc.lineChart('#chart1')
.width(900)
.height(200)
.margins({top: 20, right: 20, bottom: 20, left: 50})
.dimension(dateDimension)
.group(dateGroup)
.keyAccessor(d => new Date(d.key + '-01'))
.x(d3.time.scale().domain([new Date(2016, 0, 1), new Date(2017, 0, 1)]))
.round(d3.time.month.round)
.xUnits(d3.time.months)
.elasticY(true);
dc.lineChart('#chart2')
.width(900)
.height(200)
.margins({top: 20, right: 20, bottom: 20, left: 50})
.dimension(dateDimension)
.group(createCumulativeGroup(dateGroup)) // use fake group here instead of real group
.keyAccessor(d => new Date(d.key + '-01'))
.x(d3.time.scale().domain([new Date(2016, 0, 1), new Date(2017, 0, 1)]))
.round(d3.time.month.round)
.xUnits(d3.time.months)
.elasticY(true);
}
render(generateData());
dc.renderAll();
}());
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>dc.js cumulative chart</title>
<link rel="stylesheet" type="text/css" href="https://dc-js.github.io/dc.js/css/dc.css"/>
</head>
<body>
<div id="chart1"></div>
<div id="chart2"></div>
<script src="https://dc-js.github.io/dc.js/js/d3.js"></script>
<script src="https://dc-js.github.io/dc.js/js/crossfilter.js"></script>
<script src="https://dc-js.github.io/dc.js/js/dc.js"></script>
<script src="https://dc-js.github.io/dc.js/js/colorbrewer.js"></script>
<script src="https://cdn.jsdelivr.net/lodash/4.17.4/lodash.js"></script>
<script src="https://unpkg.com/mersennetwister@0.2.3"></script>
<script src="chart.js"></script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment