使用 D3.js 将误差线添加到分组条形图中

Posted

技术标签:

【中文标题】使用 D3.js 将误差线添加到分组条形图中【英文标题】:Adding Error Bars to Grouped Bar Chart with D3.js 【发布时间】:2014-05-02 10:32:14 【问题描述】:

首先我想知道是否有人知道显示带有误差线的分组条形图的 D3 示例?我发现的最接近的东西是:

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

我有一个分组条形图的工作示例,我想为显示 MOE 的图表中的每个条形添加一个误差条。我需要采取哪些步骤来完成此任务?我将如何计算线的位置?这是我认为需要做的事情,请帮我填写我需要采取的步骤。

    创建 SVG 线

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

    追加

这不起作用,但它在正确的轨道上吗?

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);

【问题讨论】:

代码应该与您链接到的第一个示例中的代码非常相似,不是吗? 如果你能用你目前得到的东西来制作一个小提琴会很有帮助。 【参考方案1】:

如果您只想要直线误差线(没有顶部和底部水平线),是的,您可以使用区域或线生成器(只有区域生成器具有 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" 属性。我在this answer 中讨论了这样做,对于错误栏,形状实际上要简单得多,因为它只是直线。您可能会发现 this tutorial on the path directions syntax 是一个有用的参考。

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

【讨论】:

感谢您的回答总是很有帮助!我在这一行收到错误“错误:解析 d="MNaN,NaNLNaN,NaNZ" 的问题:errorBars.attr("d", function(d)return errorBarArea([d]);) 由于分组数据结构,它变得有点复杂。连接到误差条路径的数据必须是每个单独条的数据(因此您可以轴值),但在同一个数据对象中,它也必须具有误差范围。我已更新为 (a) 将误差范围(您为每个组定义)复制到映射函数中的各个数据点中; (b) 更改区域生成器中的比例以匹配数据; (c) 使误差条成为每个状态组内的嵌套选择;和 (d) 让你的样本变得足够大,可以看到! jsfiddle.net/CgqrY/5 太棒了。因此,如果每个年度类别“5 年以下”或“5 到 14 年”都有一个教育部,而不是每个州组的教育部,那么可以跳过将教育部复制到各个数据点的步骤吗?每个类别的 moe 是否仍可称为“moe”,或者它们是否都需要有自己唯一的名称? 是的,如果你有每个数据点的 m.o.e 值,那么你就不需要复制了。如果您的 一些 数据点有自己的值,而其他数据点是每个类别,则您需要检查 moe = category.moe || state.moe 的形式来分配第一个(如果存在),如果不存在,则分配第二个(确切代码当然取决于您的数据结构)。无论哪种方式,您都希望最终数据对象具有相同的属性名称,以便绘图函数无需复杂检查即可访问它。

以上是关于使用 D3.js 将误差线添加到分组条形图中的主要内容,如果未能解决你的问题,请参考以下文章

如何在 R 中的 ggplot 中为条形图添加误差线

如何在列的分组条形图上添加误差线

R中带有误差线的分组条形图

如何在 matplotlib 条形图中增加误差线的粗细?

使用 d3.js 制作分组条形图

d3.js 如何在条形图中添加线条