2012-04-12 90 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()); 

最後,您可以添加一個座標軸在頂部顯示刻度標記。您也可以計算填充樣式(或甚至梯度)來改變區分正值和負值的外觀。全部放在一起: