Search code examples
dc.jscrossfilter

How can I have a custom reduce function in my crossfilter groups?


I have a numeric field in my dataset. I am doing and dashboard to filter on this field through year, age, and so on. The fact is that this field is a ratio over a sample of the population, therefore when I am creating a var ratesPerAge = ageDim.group().reduceSum(function(d) {return +d.suicidesPercentage}); the rate of each record is summed up since I am using .reduceSum().

My goal is to have something like the average and having each time the average rate on the filtered rows.

I have tried to implement the solution I want using this function I have found in another thread.

var col1DimTotal = col1Dim.group().reduce(reduceAdd, reduceRemove, 
  reduceInitial);

function reduceAdd(p, v) {
  ++p.count;
  p.total += v.value;
  return p;
}

function reduceRemove(p, v) {
  --p.count;
  p.total -= v.value;
  return p;
}

function reduceInitial() {
  return {count: 0, total: 0};
}

However, this did not achieve what I wanted.

This is my rate dimension and the grouping with another dimension:

 var ratesDim = ndx.dimension(function(d) {return 
 d.suicidesPercentage;});
 var ageDim = ndx.dimension(function(d) {return d.age});  
 var ratesPerAge = ageDim.group().reduceSum(function(d) {return 
 +d.suicidesPercentage}); 

I would like to filter trough the average rate of the rows I am selecting.


Solution

  • I think I solved this and I managed to achieve what I wanted:

    var yearDim  = ndx.dimension(function(d) { return new Date(d.year); });
    function reduceAddAvg(p,v) {
        ++p.count
        p.sum += v.suicidesPercentage;
        p.avg = p.sum/p.count;
        return p;
    }
    function reduceRemoveAvg(p,v) {
        --p.count
        p.sum -= v.suicidesPercentage;
        p.avg = p.count ? p.sum/p.count : 0;
        return p;
    }
    function reduceInitAvg() {
        return {count:0, sum:0, avg:0};
    }
    
    var ratesPerYear = yearDim.group().reduce(reduceAddAvg, reduceRemoveAvg, reduceInitAvg);
    
     yearChart // line chart
         .width(660)
         .height(400)
         .dimension(yearDim)
         .group(ratesPerYear).valueAccessor(function (d) {
              return d.value.avg;
          }) // this is the reference of the AVG
         .x(d3.scaleTime().domain([new Date("January 1, 1987 00:00"), new 
            Date("January 4, 2015 00:00:00")]))
         .elasticY(true)
         .controlsUseVisibility(true)
         .yAxisLabel("Rates over 100k people")
         .xAxisLabel("Year")
         .centerBar(true);