数据可视化

Data Visualization



@harrysun

 

微博: frontnode

QQ: 2080432723

邮箱: frontnode@126.com

开源地址: github.com/frontnode


Web开发,流程改进,最佳实践,性能优化






数据可视化是什么?
为什么需要数据可视化?
我们该如何可视化数据呢?





一般的数据图表都可以拆分成最基本的两类元素

  1. 所描述的事物
  2. 这个事物的数值

我们暂且将其分别定义为指标和指标值。

比如一个性别分布中,男性占比30%,女性占比70%,

那么指标就是男性、女性,指标值对应为30%、70%。

1. 将指标值图形化

  • 一个指标值就是一个数据, 将数据的大小以图形的方式表现。 比如用柱形图的长度或高度表现数据大小, 这也是最常用的可视化形式。



2. 将指标图形化

  • 一般用与指标含义相近的icon来表现,使用场景也比较多


3.将指标关系图形化

  • 指标之间往往具有一些关联特征,如从简单到复杂、从低级到高级、从前到后等等。

小结

  • 根据之前3步,可将指标、指标值和指标关系分别进行图形化处理。

  • 以最简单的性别分布为例,可以得到一个线性的可视化过程,如下 

4. 将时间和空间可视化

  • 时间

    通过时间的维度来查看指标值的变化情况,一般通过增加时间轴的形式,也就是常见的趋势图。


  • 空间

    当图表存在地域信息并且需要突出表现的时候,可用地图将空间可视化,地图作为主背景呈现所有信息点。



5. 将数据进行概念转换

  • 先看下生活中的概念转换,当我们需要喝水时,通常会说:给我来一杯水;而不会说:给我来30ml的水。在这里,30ml是一个实际数据,但是难以感知,所以用一杯的概念来转换。 同样在数据可视化,有时需要对数据进行概念转换,可加深用户对数据的感知。常用方法有对比和比喻。 

下图是一个介绍中国烟民数量的图表:如果只看左半部分中国烟民的数量:32000000,知道数据量级很大,但具体有多大却很难感知;直到看到右半部分:中国烟民数量超过了美国人口总和,这样一对比,对数据的感知就加深了。

6.让图表“动”起来

  • 数据图形化完成后,可结合实际情况,将其变为动态化和可操控性的图表,用户在操控过程中能更好地感知数据的变化过程,提升体验。 
  • 实现动态化通常以下两种方式: 交互和动画。

交互

交互包括鼠标浮动、点击、多图表时的联动响应等等

动画

  • 包括增加入场动画、交互过程的动画、播放动画等等。 
  • 入场动画:即在页面载入后,给图表一个“生长”的过程,取代“数据载入中”这样的提示文字。 
  • 交互动画:用户发生交互行为后,通过动画形式给以及时反馈。 
  • 播放动画:一般来是提供播放功能,像看视频一样,让用户能够完整看到数据随时间变化的过程。



数据可视化工具


  • Google Chart API 

    Google Chart API工具集中取消了静态图片功能,目前只提供动态图表工具。能够在所有支持SVG\Canvas和VML的浏览器中使用,但是Google Chart的一个大问题是:图表在客户端生成,这意味着那些不支持JavaScript的设备将无法使用,此外也无法离线使用或者将结果另存其他格式,之前的静态图片就不存在这个问题。尽管存在上述问题,不可否认的是Google Chart API的功能异常丰富,如果没有特别的定制化需要,或者对Google视觉风格的抵触,那么你大可以从Google Chart开始。

  • Flot

    Flot是一个优秀的线框图表库,支持所有支持canvas的浏览器(目前主流的浏览器如火狐、IE、Chrome等都支持)。

数据可视化工具


  • Raphaël

    Raphaël是创建图表和图形的JavaScript库,与其他库最大的不同是输出格式仅限SVG和VML。SVG是矢量格式,在任何分辨率下的显示效果都很好。

  • D3

    D3(Data Driven Documents)是支持SVG渲染的另一种JavaScript库。但是D3能够提供大量线性图和条形图之外的复杂图表样式,例如Voronoi图、树形图、圆形集群和单词云等。虽然D3能够提供非常花哨的互动图表,但你在选择数据可视化工具时,需要牢记的一点是:知道在何时保持简洁。

数据可视化工具


  • 作为用来分析大数据集的统计组件包,R是一个非常复杂的工具,需要较长的学习实践,学习曲线也是本文所介绍工具中最陡峭的。但是R拥有强大的社区和组件库,而且还在不断成长。当你能驾驭R的时候,一切付出都是物有所值的。

D3的使用


下载官方包 d3.v3.zip 或者添加如下代码:
<script src="http://d3js.org/d3.v3.min.js" charset="utf-8"><script/>

数据

var dataset = [1,2,3,4,5];
d3.select("body").selectAll("p")
    .data(dataset)
    .enter()
    .append("p")
    .text("New paragraph!");

结果如下图

详细的解释
d3.select("body") 
        选择DOM 中的body 元素,把它交给连缀方法中的下一个方法。 .selectAll("p")
        选择DOM 中的所有段落。因为还没有段落,所以返回空元素。可以认为这个空元素代表马上就会创建的段落。
.data(dataset) 
        解析并数出数据值。dataset 数组中有5 个值,因而此后的所有方法都将执行五遍,每次针对一个值。
.enter() 
        要创建新的绑定数据的元素,必须使用enter()。这个方法会分析当前选择的DOM 元素和传给它的数据,如果数据值比对应的DOM 元素多,就创建一个新的占位元素。然后把这个新占位元素的引用交给链中的下一个方法。 
.append("p") 
        取得由enter() 创建的空占位元素,并把一个p 元素追加到相应的DOM 中。然后它再把自己刚创建的元素交给链中的下一个方法。
.text("New paragraph!") 
        取得新创建的p 元素,插入文本值。

将最后一行修改为 

 .text(function(d) { return d; }); 

结果如下

我们用数据填充了每个段落,机关都在data() 方法里。在连缀方法中,只要调用data() 了,就可以随时创建一个接收d 为输入的匿名函数。与当前元素对应,方法data() 确保了每个d 都会被赋予原始数据集中的一个值。随着D3 遍历每个元素,“当前元素”的这个值也会跟着变化。

SVG绘制

首先要创建一个SVG 元素,以便在其中保存所有图形,先找到文档的body 元素,然后在结束的 标签前添加一个新的svg 元素,并设置长宽,代码如下
 var svg = d3.select("body")
    .append("svg") 
    .attr("width", 500) 
    .attr("height", 50);  
添加一些数据 
var dataset = [ 5, 10, 15, 20, 25 ];  
使用data() 迭代每个数据点,为它们分别创建一个圆形 
 var circles = svg.selectAll("circle") 
    .data(dataset)
    .enter()
    .append("circle");  

最后设置图形的样式

circles.attr("cx", function(d, i) {
        return (i * 50) + 25;
    })//设置x的位置
    .attr("cy", 50 / 2)//设置y的位置
    .attr("r", function(d) {
        return d;
    })//设置圆的半径
    .attr("fill", "yellow")//设置填充颜色
    .attr("stroke", "orange")//设置圆的边缘线颜色
    .attr("stroke-width", function(d) {
        return d / 2;
    });//设置圆的边缘线的宽度

结果如下图

R的使用

Ubuntu安装R
编辑资源列表
sudo vi /etc/apt/sources.list  

添加资源

deb http://mirrors.ustc.edu.cn/CRAN/bin/linux/ubuntu/ precise/  

安装

apt-get update 
apt-get install r-base 
apt-get install r-base-dev  
启动R
R 
退出R
q() 

R语言绘图的几个小例子

绘制0~100  x^2的曲线
curve(x^2, 0, 100); 
数字0~20,表示21种不同的符号
curve(x/20,0,20,lty=0); for (i in 0:20) {points(i,0.5,pch=i);}
绘制散点图
x=seq(0, 10, 0.1); y=sin(x)+rnorm(101); #x的值必须排序,rnorm(n)则是按正态分布随机产生n个数据。
plot(x,y); #做散点图 






Questions?