直方圖用于描述概率分布,D3 提供了直方圖的布局 Histogram 用于轉換數據。
[](http://www.ourd3js.com/wordpress/wp-content/uploads/2014/12/501.png)
假設有數組 a = [10, 11, 11.5, 12.5, 13, 15, 19, 20 ],現在把10~20的數值范圍分為5段,即:
10~12, 12~14, 14~16, 16~18, 18~20
那么數組 a 的各數值都落在這幾段區域的哪一部分呢?經過計算,可以知道,這5段分別具有的元素個數為:
3, 2, 1, 0 , 2
將這個用圖形展示出來的,就是直方圖。好了,開始制作吧~
## 1. 數據
首先生成隨機數據:
~~~
var rand = d3.random.normal(0,25);
var dataset = [];
for(var i=0;i<100;i++){
dataset.push( rand() );
}
~~~
d3.random.normal 生成一個函數,這個函數能夠按正態(高斯)分布隨機生成數值。要傳入兩個參數,第一個是位置參數,第二個是尺寸參數。關于正態分布的定義,可參見[維基百科](http://zh.wikipedia.org/wiki/%E6%AD%A3%E6%80%81%E5%88%86%E5%B8%83)。將這個函數賦值給 rand 之后,接下來只要用 rand() 即可生成隨機數。
## 2. 布局(數據轉換)
接下來,要將上述數據進行轉換,即確定一個區間和分隔數之后,另數組的數值落在各區域里。先定義一個布局:
~~~
var bin_num = 15;
var histogram = d3.layout.histogram()
.range([-50,50])
.bins(bin_num)
.frequency(true);
~~~
- d3.layout.histogram: 直方圖的布局
- range: 區間的范圍
- bins: 分隔數
- frequency: 若值為 true,則統計的是個數;若值為 false,則統計的是概率
接下來即可轉換數據:
~~~
var data = histogram(dataset);
~~~
來看看轉換前后的數據有什么分別吧。轉換前:
[](http://www.ourd3js.com/wordpress/wp-content/uploads/2014/12/502.png)
轉換后:
[](http://www.ourd3js.com/wordpress/wp-content/uploads/2014/12/503.png)
可以看到,轉換后的數組,長度即分隔數,每一個區間內有落到此區間的數值(圖中的0,1,2,...),數值的個數(length),還有三個參數:
- x: 區間的起始位置
- dx: 區間的寬度
- y: 落到此區間的數值的數量(如果?frequency 為 true);落到此區間的概率(如果?frequency 為 false)
## 3. 繪制
繪制之前,需要定義一個比例尺,因為通常我們需要讓轉換后的 y 在希望的范圍內伸縮。
~~~
var max_height = 400;
var rect_step = 30;
var heights = [];
for(var i=0;i<data.length;i++){
heights.push( data[i].y );
}
var yScale = d3.scale.linear()
.domain([d3.min(heights),d3.max(heights)])
.range([0,max_height]);
~~~
最后,繪制圖形:
~~~
//繪制圖形
var graphics = svg.append("g")
.attr("transform","translate(30,20)");
//繪制矩形
graphics.selectAll("rect")
.data(data)
.enter()
.append("rect")
.attr("x",function(d,i){
return i * rect_step;
})
.attr("y", function(d,i){
return max_height - yScale(d.y);
})
.attr("width", function(d,i){
return rect_step - 2;
})
.attr("height", function(d){
return yScale(d.y);
})
.attr("fill","steelblue");
//繪制坐標軸的直線
graphics.append("line")
.attr("stroke","black")
.attr("stroke-width","1px")
.attr("x1",0)
.attr("y1",max_height)
.attr("x2",data.length * rect_step)
.attr("y2",max_height);
//繪制坐標軸的分隔符直線
graphics.selectAll(".linetick")
.data(data)
.enter()
.append("line")
.attr("stroke","black")
.attr("stroke-width","1px")
.attr("x1",function(d,i){
return i * rect_step + rect_step/2;
})
.attr("y1",max_height)
.attr("x2",function(d,i){
return i * rect_step + rect_step/2;
})
.attr("y2",max_height + 5);
//繪制文字
graphics.selectAll("text")
.data(data)
.enter()
.append("text")
.attr("font-size","10px")
.attr("x",function(d,i){
return i * rect_step;
})
.attr("y", function(d,i){
return max_height;
})
.attr("dx",rect_step/2 - 8)
.attr("dy","15px")
.text(function(d){
return Math.floor(d.x);
});
~~~
## 4. 結果
結果圖即本文開頭的圖片。
完整代碼請點擊下面的鏈接后,單擊右鍵后再“查看源代碼”:
[http://www.ourd3js.com/demo/J-5.0/histogram.html](http://www.ourd3js.com/demo/J-5.0/histogram.html)
### 文檔信息
- 版權聲明:署名(BY)-非商業性(NC)-禁止演繹(ND)
- 發表日期:2014 年 12 月 17 日
- 更多內容:[OUR D3.JS - 數據可視化專題站](http://www.ourd3js.com/) 和 [CSDN個人博客](http://blog.csdn.net/lzhlzz)
- 備注:本文發表于 [OUR D3.JS](http://www.ourd3js.com/) ,轉載請注明出處,謝謝