使用D3.js添加误差棒到分组条形图

5

首先,我想了解一下是否有人知道一个带有误差棒的分组条形图的D3示例?我找到的最接近的东西是:

http://tenxer.github.io/xcharts/examples/(示例自定义可视化类型:误差棒) http://bl.ocks.org/chrisbrich/5044999(点的误差棒)

我有一个工作中的分组条形图示例,我想在图表中的每个条形图上添加一个误差棒来显示MOE。我需要采取什么步骤才能完成这个操作?如何计算线的位置?这是我认为需要做的事情,请帮助我填写我需要采取的步骤。

  1. 创建SVG线

  2. 通过获取d.value + MOE和d.value - MOE的d3.max来计算线的ymin和ymax

  3. 附加

这行不通,但它是正确的吗?

var line = d3.svg.line()
    .x(function(d) {return x(d.state); })
    .y0(function(d) {return y(d.value - d.moe); })
    .y1(function(d) {return y(d.value + d.moe); })
    .interpolate("linear");

var errorBarSVG = d3.select("body").append("svg")

var errorBar = errorBarSVG.append("path")
    .attr("d", line(data))
    .attr("stroke", "red")
    .attr("stroke-width", 1.5);

代码应该与您链接到的第一个示例非常相似,不是吗? - Lars Kotthoff
如果您能生成一个示例,展示您目前所拥有的内容,那将非常有帮助。 - FernOfTheAndes
1个回答

5
如果你只想要直线误差条(没有顶部和底部的水平线),那么你可以使用面积或线生成器(只有面积生成器具有y0/y1方法)。但是,你不能一次性对所有数据调用路径生成器,你需要创建一个与数据连接的路径选择集,然后将数据对象作为一个(面积生成器)或两个点(线生成器)数组传递给生成器函数。这样应该可以实现:
var errorBarArea = d3.svg.area()
    .x(function(d) {return x(d.state); })
    .y0(function(d) {return y(d.value - d.moe); })
    .y1(function(d) {return y(d.value + d.moe); })
    .interpolate("linear");

var errorBarSVG = d3.select("body").append("svg")

var errorBars = errorBarSVG.selectAll("path")
         .data(data);

errorBars.enter().append("path");

errorBars.attr("d", function(d){return errorBarArea([d]);}) 
             //turn the data into a one-element array 
             //and pass it to the area function
    .attr("stroke", "red")
    .attr("stroke-width", 1.5);

这将为每个柱形创建一个零宽度区域路径,连接+/-点成一条直线。
如果您使用了线生成器函数,那么在将数据转换为数组时,您需要计算顶部和底部的Y值:
errorBars.attr("d", function(d){
                  return errorBarLine([{x:d.x, y:d.value - d.moe},
                                       {x:d.x, y:d.value + d.moe}]);
               })

或者,你可以使用d3.svg.diagonal来创建直线误差条。 对角函数专门设计用于从单个数据对象中提取起始和结束线点; 然后,您需要自定义sourcetarget访问器函数以创建像上面代码示例中的对象。

但是,如果您想要具有水平上下线的自定义形状误差条,则需要编写自己的函数来创建基于数据对象的路径"d"属性。 我在这个答案中讨论了如何做到这一点,对于错误栏,实际上形状会简单得多,因为它全部都是直线。 您可能会发现这篇有关路径方向语法的教程很有参考价值。

最后,您可能还想重新编写条形图代码,使每个条形图由连接到数据的<g>元素表示,然后您将矩形和误差栏路径附加到其中,而无需计算单独的数据连接。


谢谢,你的回答总是非常有帮助!我遇到了一个错误:“Error: Problem parsing d="MNaN,NaNLNaN,NaNZ" at this line: errorBars.attr("d", function(d){return errorBarArea([d]);})” - bailey
由于数据结构被分组,所以变得有点复杂。连接到误差条路径的数据必须是每个单独柱形图的数据(这样您可以轴值),但在同一数据对象中,它还必须具有误差边距。我已更新:(a)将误差边距(您定义的每个组)复制到映射函数中的各个数据点;(b)更改区域生成器中的比例尺以匹配数据;(c)使误差条成为每个状态组内的嵌套选择; (d)使您的样本moe足够大以便看到!http://jsfiddle.net/CgqrY/5/ - AmeliaBR
太棒了。因此,如果每个年龄类别“5岁以下的moe”或“5至14岁的moe”都有一个moe,而不是每个州组一个moe,则可以跳过将moe复制到各个数据点的步骤?每个类别的moe仍然可以称为“moe”,还是它们需要拥有自己独特的名称? - bailey
如果每个数据点都有自己的m.o.e值,那么您就不需要重复。如果一些数据点有自己的值,而其他数据点则是按类别划分的,则需要检查表单moe = category.moe || state.moe,如果第一个存在则分配它,否则分配第二个(确切代码当然取决于您的数据结构)。无论哪种方式,您都希望最终的数据对象具有相同属性名称,以便图形函数可以在不进行复杂检查的情况下访问它。 - AmeliaBR

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接