score:8

Accepted answer

The issue is that you are not joining correctly your data with your elements.

We need to build different scales in order to obtain the correct rangeBand value.

var x_groups = d3.scale.ordinal()
  .rangeRoundBands([0, width], .1);

var x_categories = d3.scale.ordinal();

var x_values = d3.scale.ordinal();

I created a nested data structure that will contain everything we need for our grouped bar chart approach.

var nested = d3.nest()
    .key(function(d) {
      return d.groups;
    })
    .key(function(d) {
      return d.categories;
    })
    .rollup(function(leaves) {
      return [{
        key: 'v-a',
        value: leaves[0]['value 1']
      }, {
        key: 'v-b',
        value: leaves[0]['value 2']
      }, {
        key: 'v-c',
        value: leaves[0]['value 3']
      }];
    })
    .entries(data);

Next lets configure our scales with the information we just got.

  x_groups.domain(nested.map(function(d) {
    return d.key;
  }));
  //var categories = ['A', 'B', 'C']; 
  var categories = nested[0].values.map(function(d, i) {
    return d.key;
  });
  x_categories.domain(categories).rangeRoundBands([0, x_groups.rangeBand()]);
  //var values = ['value 1', 'value 2', 'value 3']; 
  var values = nested[0].values[0].values.map(function(d, i) {
    return d.key;
  });
  x_values.domain(values).rangeRoundBands([0, x_categories.rangeBand()]);

Then we can finally start our data join. You can see that when we enter a new level of info we need to set the data function correctly.

var groups_g = svg.selectAll(".group")
  .data(nested)
  .enter().append("g")
  .attr("class", function(d) {
    return 'group group-' + d.key;
  })
  .attr("transform", function(d) {
    return "translate(" + x_groups(d.key) + ",0)";
  });

var categories_g = groups_g.selectAll(".category")
  .data(function(d) {
    return d.values;
  })
  .enter().append("g")
  .attr("class", function(d) {
    return 'category category-' + d.key;
  })
  .attr("transform", function(d) {
    return "translate(" + x_categories(d.key) + ",0)";
  });

var categories_labels = categories_g.selectAll('.category-label')
  .data(function(d) {
    return [d.key];
  })
  .enter().append("text")
  .attr("class", function(d) {
    return 'category-label category-label-' + d;
  })
  .attr("x", function(d) {
    return x_categories.rangeBand() / 2;
  })
  .attr('y', function(d) {
    return height + 25;
  })
  .attr('text-anchor', 'middle')
  .text(function(d) {
    return d;
  })

var values_g = categories_g.selectAll(".value")
  .data(function(d) {
    return d.values;
  })
  .enter().append("g")
  .attr("class", function(d) {
    return 'value value-' + d.key;
  })
  .attr("transform", function(d) {
    return "translate(" + x_values(d.key) + ",0)";
  });

var values_labels = values_g.selectAll('.value-label')
  .data(function(d) {
    return [d.key];
  })
  .enter().append("text")
  .attr("class", function(d) {
    return 'value-label value-label-' + d;
  })
  .attr("x", function(d) {
    return x_values.rangeBand() / 2;
  })
  .attr('y', function(d) {
    return height + 10;
  })
  .attr('text-anchor', 'middle')
  .text(function(d) {
    return d;
  })

var rects = values_g.selectAll('.rect')
  .data(function(d) {
    return [d];
  })
  .enter().append("rect")
  .attr("class", "rect")
  .attr("width", x_values.rangeBand())
  .attr("x", function(d) {
    return 0;
  })
  .attr("y", function(d) {
    return y(d.value);
  })
  .attr("height", function(d) {
    return height - y(d.value);
  })
  .style("fill", function(d) {
    return color(d.key);
  });

Working plnkr: https://plnkr.co/edit/qGZ1YuyFZnVtp04bqZki?p=preview


Related Query

More Query from same tag