title: d3 nested grouped bar chart
body: <p>First of all sorry if my English is difficult to understand, I'll try my best...</p>
  
  <p>I am rather new to D3.js and I'm trying to create a D3 grouped bar chart using nested data. I have looked at some solutions shared here, but they only show one-level grouping. In my case,  data will come from a csv file that has this data structure:</p>
  
  <pre><code>groups,categories,value 1,value 2,value 3
  group 1,A,61.0158803,25.903359,13.08076071
  group 1,B,71.27703826,21.0180133,7.70494844
  group 1,C,82.70203982,13.52731445,3.770645737
  group 2,A,58.85721523,28.25939061,12.88339417
  group 2,B,71.39695487,20.66010982,7.942935308
  group 2,C,82.22389321,13.68924542,4.08686137
  </code></pre>
  
  <p>The chart is intended to have two x axis, one for the groups (level 0) and one for the categories (level 1).Values 1 to 3 will display as grouped bars for each catergory, and the categories will be displayed within the corresponding group.</p>
  
  <p>The structure of the chart should be:</p>
  
  <pre><code>value 1 | value 2 | value 3 | value 1 | value 2 | value 3 | value 1 | value 2 | value 3 |
  |        category A         |          category B         |          category C         |
  |                                       group 1                                         |
  </code></pre>
  
  <p>and the same for group 2, placed contiguous.</p>
  
  <p>The problem is with the code I am working on, I get the right axis but data corresponding two both groups are shown, one on top of the other, in each group area. I am not able to link the data on the categories to their corresponding group in orther to draw them where it corresponds. </p>
  
  <p>Here is the code I've got so far:</p>
  
  <pre><code>var x0 = d3.scale.ordinal()
    .rangeRoundBands([0,width], 0);
  
  var x1 = d3.scale.ordinal()
  .rangeRoundBands([0,width]);
  
  var x2 = d3.scale.ordinal();
  
  var y = d3.scale.linear()
    .range([height,0]);
  
  var color = d3.scale.category10();
  
  var x0Axis = d3.svg.axis()
    .scale(x0)
    .orient("bottom");
  
  var x1Axis = d3.svg.axis()
    .scale(x1)
   .orient("bottom");
  
  var yAxis = d3.svg.axis()
    .scale(y)
    .orient("left");
  
  var svg = d3.select(".chart")
    .append("svg")
    .attr("class", "svg")
    .attr("viewBox", "" + margin* -1 + " " + margin* -1 + " " + (width + margin*2) + " " + (height + margin *2) + "")
    .attr ("preserveAspectRatio", "xMidYMid")
    .attr("width", "100%")
    .attr("height", "100%")
  
  
  
  d3.csv("../data/EQ01.csv", function(error, data){
    if (error) throw error;
  
   var seriesNames = d3.keys(data[0]).filter(function(key) { return key !== "categories" &amp;&amp; key !== "groups";});
  
    data.forEach(function(d) {
   d.values = seriesNames.map(function(name) { return {
       xValue: name,
       yValue: +d[name]
     };
   });
     });
  
     nested = d3.nest()
        .key(function(d) { return d.groups})
        .key(function(d) { return d.categories})
        .entries(data);
  
    y.domain([0, d3.max(data, function(d) { return d3.max(d.values, function(d) { return d.yValue; }); })]);
    x0.domain(nested.map(function(d) {return d.key;}));
    x1.domain(data.map(function(d) { return d.categories; })).rangeRoundBands([0, x0.rangeBand() ], 0.1);
    x2.domain(seriesNames).rangeRoundBands([0, x1.rangeBand()], 0);
  
    svg.append("g")
      .attr("class", "x0 axis")
      .attr("transform", "translate(0," + (height+30) + ")")
      .call(x0Axis);
  
    svg.append("g")
     .attr("class", "y axis")
     .call(yAxis)
  
    var group = svg.selectAll(".group")
     .data(nested)
     .enter().append("g")
     .attr("class", "group")
     .attr("transform", function(d) { return "translate(" + x0(d.key) + ",0)"; });
  
    group.append("g")
     .attr("class", "x1 axis")
     .attr("transform", "translate(0," + height + ")")
     .call(x1Axis);
  
    var category = group.selectAll(".category")
     .data(data)
     .enter().append("g")
     .attr("class", "category")
     .attr("transform", function(d) { return "translate(" + x1(d.categories) + ",0)"; });
  
    category.selectAll("rect")
    .data(function(d) { return d.values; })
    .enter().append("rect")
    .attr("width", x2.rangeBand())
    .attr("x", function(d) { return x2(d.xValue); })
    .attr("y", function(d) { return y(d.yValue); })
    .attr("height", function(d) { return height - y(d.yValue); })
    .style("fill", function(d){return color(d.xValue)})
  </code></pre>
  
  <p>Many thanks in advance for the help!</p>