带有负值的条形图 [英] Bar chart with negative values

查看:28
本文介绍了带有负值的条形图的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我需要创建一个可以具有负值的 d3 条形图.理想情况下,应根据数据范围计算轴零位置,但我会采用假设对称正负范围的解决方案,即它始终位于图表的中间.

I need to create a d3 bar chart that can have negative values. Ideally the axis zero position should be calculated based on the extent of the data, but I'd settle for a solution that assumes symmetric positive and negative extent, i.e. that it would be always in the middle of the chart.

这是我想要实现的目标的示例.

Here's an example of what I'd like to achieve.

推荐答案

好的,假设您有一个数字数组作为您的数据集,其中包括一些正值和负值:

OK, let's say you have an array of numbers as your dataset, and this includes some positive and negative values:

var data = [-15, -20, -22, -18, 2, 6, -26, -18];

您需要两个尺度来构建条形图.您需要一个定量标度(通常是 线性标度)来计算沿线的条形位置x 轴和第二个 序数比例来计算条沿 y 轴的位置.

You'll want two scales to construct a bar chart. You need one quantitative scale (typically a linear scale) to compute the bar positions along the x-axis, and a second ordinal scale to compute the bar positions along the y-axis.

对于定量尺度,您通常需要计算数据的域,该域基于最小值和最大值.一个简单的方法是通过 d3.extent:

For the quantitative scale, you typically need to compute the domain of your data, which is based on the minimum and maximum value. An easy way to do that is via d3.extent:

var x = d3.scale.linear()
    .domain(d3.extent(data))
    .range([0, width]);

您可能还想很好比例以稍微四舍五入范围.再举一个例子,有时您希望零值位于画布中间,在这种情况下,您需要取最小值和最大值中的较大值:

You might also want to nice the scale to round the extent slightly. As another example, sometimes you want the zero-value to be centered in the middle of the canvas, in which case you'll want to take the greater of the minimum and maximum value:

var x0 = Math.max(-d3.min(data), d3.max(data));

var x = d3.scale.linear()
    .domain([-x0, x0])
    .range([0, width])
    .nice();

或者,您可以对任何您想要的域进行硬编码.

Alternatively, you can hard-code whatever domain you want.

var x = d3.scale.linear()
    .domain([-30, 30])
    .range([0, width]);

对于 y 轴,您需要使用 rangeRoundBands 将垂直空间划分为每个条形的条带.这还可以让您指定条形之间的填充量.序数刻度通常与一些识别数据一起使用——例如名称或唯一 ID.但是,您也可以将序数标度与数据的索引结合使用:

For the y-axis, you'll want to use rangeRoundBands to divide the vertical space into bands for each bar. This also lets you specify the amount of padding between bars. Often an ordinal scale is used with some identifying data—such as a name or a unique id. However, you can also use ordinal scales in conjunction with the data's index:

var y = d3.scale.ordinal()
    .domain(d3.range(data.length))
    .rangeRoundBands([0, height], .2);

现在您已经有了两个比例尺,您可以创建 rect 元素来显示条形图.一个棘手的部分是在 SVG 中,矩形根据其左上角定位(xy 属性).所以我们需要使用 x- 和 y-scales 来计算左上角的位置,这取决于相关值是正值还是负值:如果值为正,则数据值确定条的右边缘,如果为负,则确定条的左边缘.因此这里的条件:

Now that you've got your two scales, you can create the rect elements to display the bars. The one tricky part is that in SVG, rects are positioned (the x and y attributes) based on their top-left corner. So we need to use the x- and y-scales to compute the position of the top-left corner, and that depends on whether the associated value is positive or negative: if the value is positive, then the data value determines the right edge of the bar, while if it's negative, it determines the left edge of the bar. Hence the conditionals here:

svg.selectAll(".bar")
    .data(data)
  .enter().append("rect")
    .attr("class", "bar")
    .attr("x", function(d, i) { return x(Math.min(0, d)); })
    .attr("y", function(d, i) { return y(i); })
    .attr("width", function(d, i) { return Math.abs(x(d) - x(0)); })
    .attr("height", y.rangeBand());

最后,您可以添加一个轴以在顶部显示刻度线.您还可以计算填充样式(甚至渐变)来改变正值和负值的外观差异.综合起来:

Lastly, you can add an axis to display tick marks on top. You might also compute a fill style (or even a gradient) to alter the differentiate the appearance of positive and negative values. Putting it all together:

这篇关于带有负值的条形图的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆