Javascript D3中使用内部JSON变量的堆叠条形图

Javascript D3中使用内部JSON变量的堆叠条形图,javascript,json,d3.js,Javascript,Json,D3.js,因此,尝试在D3.js中创建一个堆叠条形图。我已经让轴工作了,但是图形数据没有显示,有什么想法我哪里出错了吗 JS: var svg = d3.select("#recovery__table"), margin = {top: 20, right: 20, bottom: 30, left: 40}, width = +svg.attr("width") - margin.left - margin.right, height = +svg.attr("height")

因此,尝试在D3.js中创建一个堆叠条形图。我已经让轴工作了,但是图形数据没有显示,有什么想法我哪里出错了吗

JS:

var svg = d3.select("#recovery__table"),
    margin = {top: 20, right: 20, bottom: 30, left: 40},
    width = +svg.attr("width") - margin.left - margin.right,
    height = +svg.attr("height") - margin.top - margin.bottom,
    aspect = width/height,
    g = svg.append("g").attr("transform", "translate(" + margin.left + "," + margin.top + ")");

var x = d3.scaleBand()
    .rangeRound([0, width])
    .padding(0.1)
    .align(0.1);

var y = d3.scaleLinear()
    .rangeRound([height, 0]);

var z = d3.scaleOrdinal()
    .range(["#717C8B", "#7FDDC3", "#39B3CD"]);

var stack = d3.stack();

data.forEach(function(d) {
    d.year = d['trades.closed_half_year_year'];
    d.loss = d['loss'];
    d.recovered = d['recovered'];
    d.recovery = d['in_recovery'];
    d.total = d.loss + d.recovery + d.recovered;
});

var div = d3.select("body").append("div")
    .attr("class", "tooltip3")
    .style("opacity", "0");

 x.domain(data.map(function(d) { return d.year; }));
 y.domain([0, d3.max(data, function(d) { return d.total; })]).nice();
 z.domain(d3.keys(data[0]).filter(function(key){ return key == 'loss' && key == 'recovered' && key == 'in_recovery' }));

 g.selectAll(".serie")
      .data(data)
      .enter().append("rect")
      .attr("class", "bar")
      .attr("fill", function(d){ return z(d.keys); })
      .attr("x", function(d) { return x(d.year); })
      .attr("width", x.bandwidth())
      .attr("y", function(d) { return y(d.total); })
      .attr("height", function(d) { return y[0] - y[1]; })
      .on("mouseover", function(d) {
        var value = parseInt($(this).attr('data-value'));
        div.transition()
          .duration(200)
          .style("opacity", .5);
        div.html(d.data.year + "<br/>£" + total.formatMoney())
          .style("left", (d3.event.pageX) + "px")
          .style("top", (d3.event.pageY - 28) + "px");
      })
      .on("mouseout", function(d) {
        div.transition()
          .duration(500)
          .style("opacity", 0);
      });
    ;

 g.append("g")
      .attr("class", "axis axis--x")
      .attr("transform", "translate(0," + height + ")")
      .attr('x', 20)
      .call(d3.axisBottom(x));

 g.append("g")
      .attr("class", "axis axis--y")
      .call(d3.axisLeft(y).ticks(5, "s"))
      .append("text")
      .attr("x", 2)
      .attr("y", y(y.ticks(10).pop()))
      .attr("dy", "0.35em")
      .attr("text-anchor", "start")
      .attr("fill", "#000");

 var legend = g.selectAll(".legend")
      .data(data)
      .enter().append("g")
      .attr('width', 100)
      .attr("class", "legend")
      .attr('transform', function(d, i) {
        var horz = 100*i;                       // NEW
        var vert = 0;
        if (horz >= width) {
          horz = 100 * (i - 3);
          vert = 40;
        }

        return 'translate(' + horz + ',' + vert + ')';        // NEW
      })
      .style("font", "10px sans-serif");

 legend.append("rect")
      .attr("x", "33%")
      .attr("width", 18)
      .attr("height", 18)
      .attr("fill", z);

 legend.append("text")
      .attr("x", "43%")
      .attr("y", 9)
      .attr("dy", ".35em")
      .attr("text-anchor", "end")
      .text(function(d) { return d; });
本质上,需要将丢失、恢复和恢复堆叠在图上,但没有像前面提到的那样将数据加载到图上


有什么想法吗?

有一个小问题,您使用的数据是JSON,因此对象将以字符串形式接收值,您必须将它们正确地解析为数字。将字符串解析为数字的简单方法如下:

d.loss = +d['loss'];
d.total = "£456,324.33" + 0 + "£4,324.33"  // "£456,324.330£4,324.33"
但即使我们这样做了,我们仍然会有你的数据问题。为什么?因为数据集中的某些数字已格式化:

"loss":"£456,324.33" 
因此,如果您正尝试这样做:

d.total = d.loss + d.in_recovery + d.recovered;
您将获得一个无效值,因为我们可能会发出如下操作:

d.loss = +d['loss'];
d.total = "£456,324.33" + 0 + "£4,324.33"  // "£456,324.330£4,324.33"
这将改变我们图表中的比例

y.domain([0, d3.max(data, function(d) {
   return d.total;
})]).nice(); // spooky domain here :S
让我们来处理您的值的格式(假设值总是按照您提供的JSON中的方式进行格式设置):

现在我们有了一个正确的数据集,我们应该准备好开始使用d3和
堆栈
布局:

var keys = ['loss', 'recovered', 'in_recovery']; // Declare the keys we will want in our stack
z.domain(keys); // Set them as our z domain so we can retrieve our fill color
var stackLayout = d3.stack().keys(keys)(data); // Create our stack layout
这将创建以下结构:

[
   [
      [
         0,
         0
      ],
      [
         0,
         0
      ],
      [
         0,
         456324.33
      ]
      // key: loss
   ],
   [
      [
         0,
         0
      ],
      [
         0,
         457468.31
      ],
      [
         456324.33,
         2780558.6750000003
      ]
      // key: recovered
   ],
   [
      [
         0,
         0
      ],
      [
         457468.31,
         2348035.31
      ],
      [
         2780558.6750000003,
         3113891.6750000003
      ]
      // key: in_recovery
   ]
]
通过上面的结构,我们现在可以按键块创建条形图,因为您可以看到每个数组有三个值和一个键。我们需要为每个数组元素创建一个元素:

g.selectAll(".serie")
  .data(stackLayout) // Set stack layout as data
  .enter()
  .append("g") // Creating group for each key
  .attr("fill", function(d) { return z(d.key); }) // Fill inner elements with the color provided by our z Scale
  .selectAll("rect") 
  .data(function(d) { // Use the inner array to create our rects
    return d;
  })
  .enter().append("rect")
  .attr("x", function(d) { // Position by our x Scale
    return x(d.data.year);
  })
  .attr("y", function(d) { // Position by our y Scale
    return y(d[1]);
  })
  .attr("height", function(d) { // Find the height value by using the values provided in the inner arrays
    return y(d[0]) - y(d[1]);
  })
  .attr("width", x.bandwidth()); 
我们还必须对标签做一些更改:

var legend = g.selectAll(".legend")
  .data(keys.reverse()) // Use our keys
  .enter().append("g")
  .attr("class", "legend")
  .attr('transform', function(d, i) {
    var horz = width - margin.right - (100 * i); // NEW
    var vert = 0;
    return 'translate(' + horz + ',' + vert + ')'; // NEW
  })
  .style("font", "10px sans-serif");

legend.append("text")
  .attr("x", "-5")
  .attr("y", 9)
  .attr("dy", ".35em")
  .attr("text-anchor", "end")
  .text(function(d) {
    return d;
  });
工作plnkr: