JSFiddle - React, Tailwind, and code Playground
by Gordon Woodhull
HTML
<script src="https://unpkg.com/d3@5/dist/d3.js"></script>
<script src="https://unpkg.com/crossfilter2@1.4/crossfilter.js"></script>
<script src="https://rawgit.com/crossfilter/reductio/master/reductio.js"></script>
<script src="https://npmcdn.com/universe@latest/universe.js"></script>
<script src="https://unpkg.com/dc@4/dist/dc.js"></script>
<link rel="stylesheet" href="https://unpkg.com/dc@4/dist/style/dc.css">
<div id="bubble"></div>
JavaScript
const yearlyBubbleChart = new dc.BubbleChart('#yearly-bubble-chart');
d3.csv('https://dc-js.github.io/dc.js/ndx.csv')
.then(data => {
// Since its a csv file we need to format the data a bit.
const dateFormatSpecifier = '%m/%d/%Y';
const dateFormat = d3.timeFormat(dateFormatSpecifier);
const dateFormatParser = d3.timeParse(dateFormatSpecifier);
const numberFormat = d3.format('.2f');
data.forEach(d => {
d.dd = dateFormatParser(d.date);
d.month = d3.timeMonth(d.dd); // pre-calculate month for better performance
d.close = +d.close; // coerce to number
d.open = +d.open;
});
const ndx = crossfilter(data);
// Dimension by year
const yearlyDimension = ndx.dimension(d => d3.timeYear(d.dd).getFullYear());
// Maintain running tallies by year as filters are applied or removed
const yearlyPerformanceGroup = yearlyDimension.group().reduce(
/* callback for when data is added to the current filter results */
(p, v) => {
++p.count;
p.absGain += v.close - v.open;
p.fluctuation += Math.abs(v.close - v.open);
p.sumIndex += (v.open + v.close) / 2;
p.avgIndex = p.sumIndex / p.count;
p.percentageGain = p.avgIndex ? (p.absGain / p.avgIndex) * 100 : 0;
p.fluctuationPercentage = p.avgIndex ? (p.fluctuation / p.avgIndex) * 100 : 0;
return p;
},
/* callback for when data is removed from the current filter results */
(p, v) => {
--p.count;
p.absGain -= v.close - v.open;
p.fluctuation -= Math.abs(v.close - v.open);
p.sumIndex -= (v.open + v.close) / 2;
p.avgIndex = p.count ? p.sumIndex / p.count : 0;
p.percentageGain = p.avgIndex ? (p.absGain / p.avgIndex) * 100 : 0;
p.fluctuationPercentage = p.avgIndex ? (p.fluctuation / p.avgIndex) * 100 : 0;
return p;
},
/*...