dadadima
dadadima

Reputation: 938

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.

Upvotes: 3

Views: 886

Answers (1)

dadadima
dadadima

Reputation: 938

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);

Upvotes: 1

Related Questions