我需要创建一个可以具有负值的d3条形图。理想情况下,应该根据数据的范围来计算坐标轴零点位置,但是我会找到一个解决方案,假定对称的正面和负面的范围,即它总是在图表的中间。负值的条形图
下面是我想达到的一个例子。
我需要创建一个可以具有负值的d3条形图。理想情况下,应该根据数据的范围来计算坐标轴零点位置,但是我会找到一个解决方案,假定对称的正面和负面的范围,即它总是在图表的中间。负值的条形图
下面是我想达到的一个例子。
OK,让我们假设你有一个数字为您的数据集的数组,这包括一些积极和消极的价值观:
var data = [-15, -20, -22, -18, 2, 6, -26, -18];
你会想要两个尺度,构建柱状图。您需要一个定量标度(通常为linear scale)来计算沿轴的轴位置,以及第二个轴向位置,以计算沿轴的轴位置。
对于定量范围,通常需要计算基于最小值和最大值的数据域。一个简单的方法就是通过d3.extent:
var x = d3.scale.linear()
.domain(d3.extent(data))
.range([0, width]);
您可能还需要nice规模略圆的程度。再举一个例子,有时你想在画布中央,在这种情况下,你要采取的最小值和最大值中的较大者为中心的零值:
var x0 = Math.max(-d3.min(data), d3.max(data));
var x = d3.scale.linear()
.domain([-x0, x0])
.range([0, width])
.nice();
或者,您可以硬编码任何你想要的域名。
var x = d3.scale.linear()
.domain([-30, 30])
.range([0, width]);
对于Ÿ轴,你需要使用rangeRoundBands的垂直空间划分为每个条带。这也可以让你指定条之间的填充量。对于一些识别数据通常使用序数标度 - 例如名称或唯一标识。但是,您也可以结合使用顺序尺度与数据的指数:
var y = d3.scale.ordinal()
.domain(d3.range(data.length))
.rangeRoundBands([0, height], .2);
现在,你有你的两个尺度,你可以创建矩形元素,以显示条。一个棘手的部分是在SVG中,根据其左上角定位了rects(x
和y
属性)。因此,我们需要使用x和和 -scales来计算左上角的位置,这取决于关联值是正值还是负值:如果值为正数,则数据值确定条的右边缘,如果为负,则确定条的左边。因此,这里的条件如下:
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());
最后,您可以添加一个坐标轴在顶部显示刻度标记。您也可以计算填充样式(或甚至梯度)来改变区分正值和负值的外观。全部放在一起: