【 D3.js 进阶系列 — 5.0 】 直方图

直方图用于描写叙述概率分布,D3 提供了直方图的布局 Histogram 用于转换数据。

假设有数组 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 生成一个函数,这个函数能够按正态(高斯)分布随机生成数值。要传入两个參数,第一个是位置參数,第二个是尺寸參数。关于正态分布的定义,可參见维基百科。将这个函数赋值给 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);

来看看转换前后的数据有什么分别吧。转换前:

转换后:

能够看到,转换后的数组,长度即分隔数,每个区间内有落到此区间的数值(图中的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

文档信息

时间: 2024-10-10 16:12:31

【 D3.js 进阶系列 — 5.0 】 直方图的相关文章

【 D3.js 进阶系列 — 1.0 】 CSV 表格文件的读取

在入门系列的教程中,我们常用 d3.json() 函数来读取 json 格式的文件.json 格式很强大,但对于普通用户可能不太适合,普通用户更喜欢的是用 Microsoft Excel 或 OpenOffice Calc 等生成的表格文件,因为简单易懂,容易编辑.                       Microsoft Excel 通常会保存为 xls 格式, OpenOffice Calc 通常会保存为 ods 格式.这些格式作为表格文件来说都很强大,但要读取它们是有些麻烦的,D3

【 D3.js 进阶系列 — 6.0 】 拖拽的应用(Drag)

拖拽(Drag)是交互式中很重要的一种,本文将讲解拖拽的使用方法. 1. drag的定义 D3中可用 d3.behavior.drag() 来定义 drag 行为. var drag = d3.behavior.drag() .on("drag", dragmove); function dragmove(d) { d3.select(this) .attr("cx", d.cx = d3.event.x ) .attr("cy", d.cy =

【 D3.js 进阶系列 — 4.0 】 绘制箭头

在 SVG 绘制区域中作图,在绘制直线和曲线时,常需要在某处添加箭头.本文介绍如何在 D3 中给直线和曲线添加箭头. 到目前为止,我们绘制 D3 的图表都是在 SVG 绘制区域内,虽然 D3 也可用 Canvas 或 WebGL 等作图,但 SVG 是最常用的.那么,用 D3 来绘制箭头,先要明白在 SVG 中是怎么绘制的. 1. 在 SVG 中定义箭头的标识 定义箭头的标识如下,先写一对 <defs> ,里面再写一对 <marker>,其中 marker 的属性的意义为: vie

【 D3.js 进阶系列 — 3.0 】 分区图

分区图( Partition ),也是 D3 的一个布局( Layout ).这个布局很有意思,可以做成方形也可能做成圆形,本文先介绍方形分区图的制作方法,这也是分区图最基本的形式. 分区图也是用于表示包含与被包含关系的. 1. 数据 本文使用[入门 - 第 9.4 章]的数据,内容为中国境内几个城市的所属关系. 2. 布局(数据转换) var partition = d3.layout.partition() .sort(null) .size([width,height]) .value(f

【 D3.js 进阶系列 】 进阶总结

进阶系列的文章从去年10月开始写的,晃眼又是4个多月了,想在年前总结一下. 首先恭祝大家新年快乐.今年是羊年吧.前段时间和朋友聊天,聊到十二生肖里为什么没猫,我张口就道:不是因为十二生肖开会的时候猫迟到了吗? 呵呵,不知道这是谁给我灌输的观点.o(>﹏<)o 进阶系列的文章分为两部分,文章前括号里写有: [D3.js 进阶系列] [D3.js 选择集与数据详解] 虽然称之为"进阶",但并不是说一定要看完"入门"才能看.由于本人能力有限,不能很好地整理成由

【 D3.js 进阶系列 — 1.1 】 其他表格文件的读取

CSV 表格文件是以逗号作为单元分隔符的,其他还有以制表符 Tab 作为单元分隔符的 TSV 文件,还有人为定义的其它分隔符的表格文件.本文将说明在 D3 中如何读取它们. 1. TSV 表格文件是什么 TSV(Tab Separated Values),制表分隔值,它和 CSV 文件仅仅是分隔符不一致.它的格式如下: name age 张三 22 李四 24 2. D3 中读取 TSV 文件 在 D3 中读取 TSV 文件的方法和 CSV 文件是一样的,只要更改一下函数名即可.方法如下: d3

【 D3.js 进阶系列 — 1.2 】 读取 CSV 文件时乱码的解决方法

在 D3 中使用 d3.csv 读取 CSV 文件时,有时会出现乱码问题.怎么解决呢? 1. 乱码问题 使用 d3.csv 读取 xxx.csv 文件时,如果 xxx.csv 文件使用的是 UTF-8 编码,不会有什么问题.当然,个人认为尽量使用 UTF-8 编码,可以在同一编码内使用各国文字. 但是,如果 xxx.csv 文件使用的是 utf-8 编码,使用 Microsoft Excel 打开的时候,可能会出现乱码,因为国内的 Excel 默认使用 GB2312 打开,而且在打开的时候不能选

【 D3.js 高级系列 — 4.0 】 矩阵树图

矩阵树图(Treemap),也是层级布局的扩展,根据数据将区域划分为矩形的集合.矩形的大小和颜色,都是数据的反映. 许多门户网站都能见到类似图1,将照片以不同大小的矩形排列的情形,这正是矩阵树图的应用. 图1  http://www.texastribune.org/2010/10/07/treemap-reveals-campaign-ad-trends/ 现以浙江.广西.江苏三省份2013年的GDP作为数据,以GDP大小作为节点的权重将其制作成矩阵树图. 1. 数据 新建一个citygdp.

【 D3.js 高级系列 — 1.0 】 文本的换行

在 SVG 中添加文本是使用 text 元素.但是,这个元素不能够自动换行,超出的部分就显示不出来了,怎么办呢? 高级系列开篇前言 从今天开始写高级系列教程.还是那句话,由于本人实力有限,不一定保证入门-进阶-高级,是一级比一级难的,大家选自己需要的阅读即可. 高级系列预计会先写一些常见的小问题(如本文)和剩下的三个布局(矩阵树图.堆栈图.捆图),然后写一些较复杂的图的制作方法,以及其交互式操作,例如:思维导图.多图联动.地图的标线标注等等. 近来嗓子像火烧一样,很不舒服,希望能快点好.o(>﹏