title: Stacked-to-Grouped Bars Transition
body: <p>This example of a stacked-to-grouped bar transition is beautiful. However, it's functioning off of a random number generator and for the life of me, I cannot figure how to replace that with my own data set.</p>
  
  <p><a href="http://bl.ocks.org/mbostock/3943967" rel="nofollow">http://bl.ocks.org/mbostock/3943967</a></p>
  
  <p>How do get this stacked-to-grouped bar transition to import and work with a .csv file instead of the random data generator?</p>
  
  <pre><code>&lt;!DOCTYPE html&gt;
  &lt;meta charset="utf-8"&gt;
  &lt;style&gt;
  
  body {
    font: 14px sans-serif;
  }
  
  .axis path,
  .axis line {
    fill: none;
    stroke: #000;
    shape-rendering: crispEdges;
  }
  
  .x.axis path {
    display: none;
  }
  
  form {
    position: absolute;
    right: 10px;
    top: 10px;
  }
  
  &lt;/style&gt;
  
  &lt;form&gt;
    &lt;label&gt;&lt;input type="radio" name="mode" value="grouped"&gt; Grouped&lt;/label&gt;
    &lt;label&gt;&lt;input type="radio" name="mode" value="stacked" checked&gt; Stacked&lt;/label&gt;
  &lt;/form&gt;
  
  &lt;script src="http://d3js.org/d3.v3.min.js"&gt;&lt;/script&gt;
  
  &lt;script&gt;
  
  var margin = {top: 20, right: 20, bottom: 30, left: 40},
      width = 1000 - margin.left - margin.right,
      height = 400 - margin.top - margin.bottom;
  
  var stack = d3.layout.stack(),
      layers = stack(d3.range(n).map(function() { return bumpLayer(m, .1); })),
      yGroupMax = d3.max(layers, function(layer) { return d3.max(layer, function(d) { return d.y; }); }),
      yStackMax = d3.max(layers, function(layer) { return d3.max(layer, function(d) { return d.y0 + d.y; }); });
  
  var x = d3.scale.ordinal()
      .rangeRoundBands([0, width], .1);
  
  var y = d3.scale.linear()
      .rangeRound([height, 0]);
  
  var color = d3.scale.ordinal()
      .range(["#aa0000", "#ffff66", "#99ff99", "#00aa00"]);
  
  var xAxis = d3.svg.axis()
      .scale(x)
      .tickSize(0)
      .tickPadding(6)
      .orient("bottom");
  
  var svg = d3.select("body").append("svg")
      .attr("width", width + margin.left + margin.right)
      .attr("height", height + margin.top + margin.bottom)
    .append("g")
      .attr("transform", "translate(" + margin.left + "," + margin.top + ")");
  
  d3.csv("data.csv", function(error, data) {
    color.domain(d3.keys(data[0]).filter(function(key) { return key !== "Year"; }));
  
    data.forEach(function(d) {
      var y0 = 0;
      d.power = color.domain().map(function(name) { return {name: name, y0: y0, y1: y0 += +d[name]}; });
      d.total = d.power[d.power.length - 1].y1;
    });
  
    data.sort(function(b, a) { return b.total - a.total; });
  
    x.domain(data.map(function(d) { return d.Year; }));
    y.domain([0, d3.max(data, function(d) { return d.total; })]);
  
    svg.append("g")
        .attr("class", "x axis")
        .attr("transform", "translate(0," + height + ")")
        .call(xAxis);
  
    svg.append("g")
        .attr("class", "y axis")
        .call(yAxis)
      .append("text")
        .attr("y", -8)
        .attr("x", 40)
        .attr("dy", "0em")
        .style("text-anchor", "end")
        .text("Power (Mw)");
  
    var year = svg.selectAll(".year")
        .data(data)
      .enter().append("g")
        .attr("class", "g")
        .attr("transform", function(d) { return "translate(" + x(d.Year) + ",0)"; });
  
    year.selectAll("rect")
        .data(function(d) { return d.power; })
      .enter().append("rect")
        .attr("width", x.rangeBand())
        .attr("y", function(d) { return y(d.y1); })
        .attr("height", function(d) { return y(d.y0) - y(d.y1); })
        .style("fill", function(d) { return color(d.name); });
  
    var legend = svg.selectAll(".legend")
        .data(color.domain().slice().reverse())
      .enter().append("g")
        .attr("class", "legend")
        .attr("transform", function(d, i) { return "translate(0," + i * 20 + ")"; });
  
    legend.append("rect")
        .attr("x", width - 800)
        .attr("width", 18)
        .attr("height", 18)
        .style("fill", color);
  
    legend.append("text")
        .attr("x", width - 770)
        .attr("y", 9)
        .attr("dy", ".35em")
        .style("text-anchor", "begin")
        .text(function(d) { return d; });
  
  });
  
    rect.transition()
      .delay(function(d, i) { return i * 10; })
      .attr("y", function(d) { return y(d.y0 + d.y); })
      .attr("height", function(d) { return y(d.y0) - y(d.y0 + d.y); });
  
    svg.append("g")
      .attr("class", "x axis")
      .attr("transform", "translate(0," + height + ")")
      .call(xAxis);
  
  d3.selectAll("input").on("change", change);
  
  var timeout = setTimeout(function() {
    d3.select("input[value=\"grouped\"]").property("checked", true).each(change);
  }, 2000);
  
  function change() {
    clearTimeout(timeout);
    if (this.value === "grouped") transitionGrouped();
    else transitionStacked();
  }
  
  function transitionGrouped() {
    y.domain([0, yGroupMax]);
  
    rect.transition()
        .duration(500)
        .delay(function(d, i) { return i * 10; })
        .attr("x", function(d, i, j) { return x(d.x) + x.rangeBand() / n * j; })
        .attr("width", x.rangeBand() / n)
      .transition()
        .attr("y", function(d) { return y(d.y); })
        .attr("height", function(d) { return height - y(d.y); });
  }
  
  function transitionStacked() {
    y.domain([0, yStackMax]);
  
    rect.transition()
        .duration(500)
        .delay(function(d, i) { return i * 10; })
        .attr("y", function(d) { return y(d.y0 + d.y); })
        .attr("height", function(d) { return y(d.y0) - y(d.y0 + d.y); })
      .transition()
        .attr("x", function(d) { return x(d.x); })
        .attr("width", x.rangeBand());
  }
  
  &lt;/script&gt;
  </code></pre>