I have a dataset (data) with the following row/column structure:
Date Category1 Category2 Revenue
30/12/2014 a x 10
30/12/2014 b x 15
31/12/2014 a x 11
1/1/2015 a x 13
2/1/2015 a x 14
2/1/2015 b x 9
2/1/2015 c z 4
...
Based on data I create a couple of dimensions and groups:
var ndx = crossfilter(data);
var cat1Dim = ndx.dimension(function(d) {return d.Category1;});
var revenuePerCat1 = cat1Dim.group().reduceSum(function(d) { return d.Revenue; });
var cat2Dim = ndx.dimension(function(d) {return d.Category2;});
var revenuePerCat2 = cat2Dim.group().reduceSum(function(d) { return d.Revenue; });
var dateDim = ndx.dimension(function(d) { return d.Date; });
var revenuePerDate = dateDim.group().reduceSum(function(d) { return d.Revenue; });
Next, I create the following charts:
a line chart; dimension = dateDim, group = revenuePerDate
a pie-chart; dimension = cat1Dim, group = revenuePerCat1
a pie-chart; dimension = cat2Dim, group = revenuePerCat2
Besides the charts I would also like to show the year-to-date value of the revenues via a numberDisplay. Initially I thought to achieve this by adding a simple if condition to the reduceSum function where I reduce the data to contain only items of the current year, like so:
var ytdRev = ndx.groupAll().reduceSum(function(d) { if(d.Date.getFullYear() == curYear) {return d.Revenue;} else{return 0;}});
A box containing a numberDisplay item is then called by:
box_ytd
.formatNumber("$,.4s")
.valueAccessor(function(d) {return Math.round(d * 1000) / 1000; })
.group(ytdRev);
This works perfectly fine if one selects one of the categories displayed in the pie-charts, but is incorrect when one also starts to filter date ranges in the line chart. Namely, instead of a year-to-date value, actually a 'date-to-date' value for the specific selection will be returned. Although this behaviour is correct from a technical perspective, I would like to know how I can instruct dc.js such that it will only take into account chart selections from a certain set of charts when rendering a numberDisplay. The selections made in the pie-charts should, however, both update the displayed selection in the line chart and the numberDisplay. Ideally, I would like to use one crossfilter instance only, but I am open to any suggestions that involve a second crossfilter as well.
EDIT:
Based on Gordon's comment I played around with a custom reduce function. Instead of ndx.groupAll() I applied the following reduce function with a .groupAll() on the dimension level:
function reduceAdd(p,v) {
if(v.Date.getFullYear() == curYear)
p.revenue += +v.Revenue;
return p;}
function reduceRemove(p,v) {
if v.Date.getFullYear() == curYear)
p.revenue -= +v.Revenue;
return p;}
function reduceInitial() {
return {revenue:0 };}
var ytdRev = dateDim.groupAll().reduce(reduceAdd, reduceRemove, reduceInitial);
The .valueAccessor in the numberDisplay is changed from d.value.revenue to d.revenue:
box_ytd
.formatNumber("$,.4s")
.valueAccessor(function(d) {return Math.round(d.revenue * 1000) / 1000; })
.group(ytdRev);
The numberDisplay will now reflect the total value for the current year for each of the selections made in the pie-charts. Date selections will only affect the pie-charts' values; the numberDisplay shares the same dimension with the line chart and hence the numberDisplay is unaffected by any selections on that dimension.