Weighted Average with Ag-grid


(5 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'm an "old" programmer who has been blogging for almost 20 years now. In 2017, I started Highline Solutions, a consulting company that helps with software architecture and full-stack development. I have two degrees from Carnegie Mellon University, one practical (Information and Decision Systems) and one not so much (Philosophy - thesis here). Pittsburgh, PA is my home where I live with my wife and 3 energetic boys.
I recently released a web app called TechRez, a "better resume for tech". The idea is that instead of sending out the same-old static PDF resume that's jam packed with buzz words and spans multiple pages, you can create a TechRez, which is modern, visual, and interactive. Try it out for free!
Got a Comment?
Comments (5)
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.
agridnoob
March 18, 2024
on which column is the group weighted average result displayed?.. can you give a sample output maybe screenshot maybe ?.. using either method plz
agridnoob
March 18, 2024
also, I am using this groupRowAggNodes for only one column where the agg has to be weighted average .. there are other columns where I am dynamically passing the aggFunc for simple aggregation like 'sum' and not sure if that interferes with this callback ..cause this isnt working in the case