Sjoerd Hagoort
Sjoerd Hagoort

Reputation: 13

Array manipulation with d3.nest and rollup

This is the array I want to reproduce:

[{ plts: 'Zlnd', values: { '150k': 4786, '200k': 1319, '250k': 249 }}
,{ plts: 'Hsls', values: { '150k': 1101, '200k': 412, '250k': 674 }}]

However, I don't get beyond the point of where 1) I have a grouping which just gives me a total sum at 'plts' level and not any of the detail elements and 2) the sum is located at the leaf level of 'values', but I need it to be at the 'plts'level.

Using this to get the flat data from mysql (which works, but does not yet give the values for the grouping):

 d3.json("php/data3.php", function (error, JsonData) {
            JsonData.forEach(function (d) {
                d['150k'] = +d['150k'];
                d['200k'] = +d['200k'];
                d['250k'] = +d['250k']; 

The result:

[{"plts":"Zlnd","150k":4786,"200k":1319,"250k":249}
,{"plts":"Hsls","150k":1101,"200k":412,"250k":674}

and this to format the flat array to the one I need:

        var nested_data = d3.nest()
             .key(function (d) { return d.plts; })
             .rollup(function (v) {
                      return {
                      total: d3.sum(v, function (g) { return +g['150k'] + g['200k'] + g['250k'];})
                             };
                       })
                      .entries(JsonData)
                  });

Any help is very appreciated!

Upvotes: 1

Views: 5082

Answers (1)

meetamit
meetamit

Reputation: 25157

This is not the use case for d3.nest. Nest would be appropriate if your data was in the form:

[
    { "plts": "Zlnd", "bin": "150k", "amount": 4786 },
    { "plts": "Zlnd", "bin": "200k", "amount": 1319 },
    { "plts": "Zlnd", "bin": "250k", "amount": 249 },
    { "plts": "Hsls", "bin": "150k", "amount": 1101 },
    { "plts": "Hsls", "bin": "200k", "amount": 412 },
    { "plts": "Hsls", "bin": "250k", "amount": 674 }
]

Then

d3.nest()
  .key(function (d) { return d.plts; })
  .entries(JsonData)

Would produce

[
  { key: "Zlnd", values: [
    { "plts": "Zlnd", "bin": "150k", "amount": 4786 },
    { "plts": "Zlnd", "bin": "200k", "amount": 1319 },
    { "plts": "Zlnd", "bin": "250k", "amount": 249 }
  ] },
  { key: "Hsls", values: [
    { "plts": "Hsls", "bin": "150k", "amount": 1101 },
    { "plts": "Hsls", "bin": "200k", "amount": 412 },
    { "plts": "Hsls", "bin": "250k", "amount": 674 }
  ] }
]

which you could rollup using

.rollup(function(values) {
  return d3.sum(values, function(v) { return v.amount; });
})

producing

[
  { key: "Zlnd", values: 6354 },
  { key: "Hsls", values: 2184 }
]

You can also use

d3.nest()
  .key(function (d) { return d.bin; })
  .entries(JsonData)

which would produce

[
  { key: "150k", values: [
    { "plts": "Zlnd", "bin": "150k", "amount": 4786 },
    { "plts": "Hsls", "bin": "150k", "amount": 1101 }
  ] },
  { key: "200k", values: [
    { "plts": "Zlnd", "bin": "200k", "amount": 1319 },
    { "plts": "Hsls", "bin": "200k", "amount": 412 }
  ] },
  { key: "250k", values: [
    { "plts": "Zlnd", "bin": "250k", "amount": 249 },
    { "plts": "Hsls", "bin": "250k", "amount": 674 }
  ] }
]

That way you can similarly use rollup to get the sum total of each bin — across all plts.

Hope that makes sense. Not sure if this is what you're trying to achieve, but it gives you a sense of what nest is good for. If none of this applies, just use vanilla javascript to derrive the values you want from the data you're loading and skip using d3.nest.

Upvotes: 7

Related Questions