Search code examples
d3.jsdc.jscrossfilterreductio

Dividing aggregate by aggregate (D3 / DC/ Crossfilter / Reductio)


Fiddle for Reference: https://jsfiddle.net/33228p1d/4/

Referencing Cost Average chart on the page. Chart rendered with the following code:

var cpa = ndx.dimension(function (d) {
  return d.location;
});
var cpaGroup = cpa.group().reduceSum(function (d) {
  return d.total;
});

And the chart itself: (styling left off for brevity)

cpaChart
    .dimension(cpa)
    .group(cpaGroup)
    .label(function (d) {
        return d.key + " $" + d.value;
    })
    .title(function (d) {
        return d.value;
    })
    .elasticX(true)
    .ordering(function (d) { return -d.value })
    .xAxis().ticks(4);

Right now, it is showing the total for Front and Back locations accurately.

What I want it to do is show total divided by number of unique PO's for that location to show the average cost per location.

So, for example, for Back I have two unique purchase orders totaling $396. What I would like to see is 396 / 2 for an average cost per location of 198.


Solution

  • If you're still willing to use Reductio, track sum and exceptionCount on the same group and then divide them in the valueAccessor accessor:

      var cpaGroup = reductio()
        .sum('total')
        .exception(function(d) { return d.po; })
          .exceptionCount(true)(cpa.group());
    
      cpaChart
            .width(400)
            .height(200)
            .margins({ top: 20, left: 10, right: 10, bottom: 20 })
            .dimension(cpa)
            .group(cpaGroup)
            .ordinalColors(['#3182bd', '#6baed6', '#9ecae1', '#c6dbef', '#dadaeb'])
            .label(function (d) {
                return d.key + " $" + (Math.round(d.value.sum / d.value.exceptionCount));
            })
            .title(function (d) {
                return d.value;
            })
            .valueAccessor(function(d) {
                return d.value.sum / d.value.exceptionCount;
            })
            .elasticX(true)
            .ordering(function (d) { return -d.value })
            .xAxis().ticks(4);
    

    Example: https://jsfiddle.net/7wbcref9/