2012-04-12 87 views
24

我需要创建一个可以具有负值的d3条形图。理想情况下,应该根据数据的范围来计算坐标轴零点位置,但是我会找到一个解决方案,假定对称的正面和负面的范围,即它总是在图表的中间。负值的条形图

下面是我想达到的一个例子。

Bar chart with negative values

回答

52

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(xy属性)。因此,我们需要使用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()); 

最后,您可以添加一个坐标轴在顶部显示刻度标记。您也可以计算填充样式(或甚至梯度)来改变区分正值和负值的外观。全部放在一起: