Weighted Average with Ag-grid


(3 comments)
August 8th 2018


One of the nice features of ag-grid (which is a kick-ass HTML 5 grid) is the ability to define an aggregate function for a given column - i.e. when grouping data, what calculation should you use for a given numeric column. Out of the box, there's support for a bunch of basic functions (sum, average, etc.), but one that's missing is a weighted average, which is extremely important in some domains (like finance).

A weighted average is defined as:

  weighted average (colA weighted by colB) = SUM(colA * colB) / SUM(colB)

After a little poking around, I figured out the following solution within ag-grid:


  var gridOptions = {
    ...
    groupRowAggNodes: groupRowAggNodes,
  };

  ...

  function groupRowAggNodes(nodes) {

    let result = {
      colA: 0,
      colB: 0
    };

    let sumColB = 0;
    let sumProduct = 0;
    nodes.forEach(node => {
      var data = node.group ? node.aggData : node.data;
      sumColB += data.colB;
      sumProduct += (data.colA * data.colB);
    });

    result.colB = sumColB;
    result.colA = sumProduct / sumColB;

    return result;
  }

If your aggregation function is in terms of just that column, then colDef.aggFunc is fine, but if you need to "reach" into other columns in order to calculate, then the groupRowAggNodes() is what you want to use. You can find the entire solution on Plunker here.

I believe that software development is fundamentally about making decisions, and so this is what I write about (mostly). In 2018 I started Highline Solutions, a consulting practice that helps companies with architecture, devops, and full-stack development. I have two degrees from Carnegie Mellon University, one in Information and Decision Systems and one in Philosophy (thesis). I live in Pittsburgh, PA with my wife and 3 energetic boys.
Got a Comment?

Comments (3)
August 10, 2018
Yes you can do it that way. Another way to do it is use valueGetter to provide both values to the aggFunc.

colDef.valueGetter = function(params) {
return {
a: params.data.colA,
b: params.data.colB,
toString: function() {
return this.a;
}
}

the toString is so that the grid will render A in the cells.

the standard aggFunc will then get all the objects with both a and b.
Ben
January 12, 2019
Cool. Thanks for sharing that.
Charbs
September 25, 2019
Found this while searching for a way to access data in different rows in the total column. Tried the Comment version and it worked, until I tried to use the export and it broke the CsvCreator.