Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Sum of nested JSON array using D3 .rollup

I'm trying to get the sum and average of each key in a nested array of objects that looks as follows:

    var data = [
    {department:'Electro',quant:{M:30, T:20, W:51, R:22, F:35 }},
    {department:'Beauty'',quant:{M:50, T:32, W:75, R:61, F: 45}},
    {department:'Apparel'',quant:{M:62, T:42, W:135, R: 82, F:89}},
    {department:'Misc',quant:{M:89, T:54, W:103, T:94, F:90}}
];

So I would need the sum of each department separately. i.e sum = { 'Elecro': 158, 'Beauty': 263}

I am using the rollup method but the examples aren't for nested arrays.

var deptSum = d3.nest()
.key(function(d) { return d.dept; })
.rollup(function(v) { return {
    count: v.length,
    total: d3.sum(v, function(d) {return d.quant; }),
    avg: d3.mean(v, function(d) {return d.quant; })
}; })
.entries(data)

console.log(JSON.stringify(deptSum))

But is giving me 0's for the sums.

like image 514
Math Stout Avatar asked Apr 16 '26 17:04

Math Stout


1 Answers

There is a D3 method to get the sum (and the average as well) inside the rollup. The problem, however, is that both d3.sum and d3.mean expect an array, but quant is just an object:

quant: {M:30, T:20, W:51, R:22, F:35 };

Solution: use the D3 method to get the property values, called d3.values. According to the documentation, it:

Returns an array containing the property values of the specified object (an associative array).

Thus, your rollup should be:

.rollup(function(v) {
    return {
        count: v.length,
        total: d3.sum(d3.values(v[0].quant)),
        avg: d3.mean(d3.values(v[0].quant))
    };
})

Here is a demo:

var data = [
    {department:'Electro',quant:{M:30, T:20, W:51, R:22, F:35 }},
    {department:'Beauty',quant:{M:50, T:32, W:75, R:61, F: 45}},
    {department:'Apparel',quant:{M:62, T:42, W:135, R: 82, F:89}},
    {department:'Misc',quant:{M:89, T:54, W:103, T:94, F:90}}
];

var deptSum = d3.nest()
.key(function(d) { return d.department; })
.rollup(function(v) { return {
    count: v.length,
    total: d3.sum(d3.values(v[0].quant)),
    avg: d3.mean(d3.values(v[0].quant))
}; })
.entries(data)

console.log(deptSum)
<script src="https://d3js.org/d3.v4.min.js"></script>
like image 160
Gerardo Furtado Avatar answered Apr 19 '26 07:04

Gerardo Furtado