Skip to content Skip to sidebar Skip to footer

Reshape Data For D3 Stacked Bar Chart

I have some csv data of the following format, that I have loaded with d3.csv(): Name, Group, Amount Bill, A, 25 Bill, B, 35 Bill, C, 45 Joe, A, 5 Joe, B, 8 But as I understand fro

Solution 1:

Yes, you are correct that in order to use d3.stack your data needs re-shaping. You could use d3.nest to group the data by name, then construct an object for each group - but your missing data will cause issues.

Instead, I'd do the following. Parse the data:

vardata = `Name,Group,Amount
    Bill,A,25
    Bill,B,35
    Bill,C,45
    Joe,A,5
    Joe,B,8`;
    
var parsed = d3.csvParse(data);

Obtain an array of names and an array of groups:

// obtain unique namesvar names = d3.nest()
    .key(function(d) { return d.Name; })
    .entries(parsed)
    .map(function(d) { return d.key; });

// obtain unique groupsvar groups = d3.nest()
    .key(function(d) { return d.Group; })
    .entries(parsed)
    .map(function(d) { return d.key; });

(Note, this is using d3.nest to create an array of unique values. Other utility libraries such as underscore have a simpler mechanism for achieving this).

Next, iterate over each unique name and add the group value, using zero for the missing data:

var grouped = names.map(function(d) { 
  var item = {
    name:  d
  };
  groups.forEach(function(e) {
    var itemForGroup = parsed.filter(function(f) {
      return f.Group === e && f.Name === d;
    });
    if (itemForGroup.length) {
      item[e] = Number(itemForGroup[0].Amount);
    } else {
      item[e] = 0;
    }
  })
  return item;
})

This gives the data in the correct form for use with d3.stack.

Here's a codepen with the complete example:

https://codepen.io/ColinEberhardt/pen/BQbBoX

It also makes use of d3fc in order to make it easier to render the stacked series.

Post a Comment for "Reshape Data For D3 Stacked Bar Chart"