数据可视化与制图理论
数据可视化的目的在于用图形化的手段,清晰有效地传达和沟通信息。常言道“一图胜千言”,原因就在于人能迅速获取和高效解读视觉信息。数据可视化的领域很广,历史也非常悠久。我们熟知的统计图表,譬如柱状图、折线图、饼图等,早在18世纪就已面世了。
18世纪 William Playfair 发明的几种常用统计图表
线、面 | 柱 | 饼 |
| | |
统计图表自 William Playfair 的时代开始,逐渐得到了越来越广泛的应用。也诞生了不少经典的案例,譬如南丁格尔19世纪50年代绘制的“玫瑰图”和法国工程师 Charles Joseph Minard 1861年绘制的“拿破仑东征”等等。
玫瑰图 | 拿破仑东征 |
| |
不过直到20世纪下半叶,统计图表的制图理论和方法才得到了进一步的改革。法国制图师 Jacques Bertin 在研究了大量的图表案例之后,发表了可视化图表设计与制图的奠基之作《the Semiology of Graphics》。
封面 | 视觉元素 |
| |
狭义的数据可视化就是把数据映射到一个二维平面上,通过人眼易于识别的视觉元素组合来表现数据。这本书为可视化提炼出几个最基础的视觉元素,为统计图表可视化工具的理论和实现奠定了基础。
图形语法
制图理论的完备,催生了越来越多的图表。计算机的普及和图形学的发展,也让统计图表得到进一步的丰富和发展。新的可视化图表层出不穷的同时,可视化图表绘制软件也越来越多,这时,在工程实现方面,有一个问题越来越突出:如何能以比较小的代价穷举尽可能多的图形?归根到底,就是如何表示一个可视化图表的问题。
Leland Wilkinson 在上世纪80年代开始开发 SYSTAT 的统计图形软件包时,也遇到了这个问题。最初的版本是枚举每一个能收集到的统计图形,最终代码量非常大,约 1.5M 左右。90年代初,他基于面向对象重构了这个项目,以一种树形结构管理图形元素,得到了更易扩展和动态的结果。这时软件包的大小下降到了 1M 以内。到了90年代末期,他和几个统计学家、计算机学家合作基于之前的工作开发了统计图形绘图工具 GPL。这个 Java 版本的软件代码量下降到了 0.5M 以下,并且沉淀出了一套稳定可靠的架构。
Leland Wilkinson 和《The Grammar of Graphics》
Leland Wilkinson | 《The Grammar of Graphics》 |
| |
《The Grammar of Graphics》就是 Wilkinson 在开发这套可视化软件的时候编写的,既有他对无数统计图表分析研究后的理论总结,也不乏实现图形语法的软件架构细节。至此,用一套语法描述任意图形的方法诞生了,编写基于图形语法的软件包有了理论依据和设计实践指导。
根据这本书的描述,统计图形的定义依靠以下几个基础语法:
声明 | 描述 |
---|---|
DATA | 从数据集生成视觉编码的数据操作 |
TRANS | 视觉编码变换(譬如rank) |
SCALE | 度量变换(譬如log) |
COORD | 定义坐标系(譬如极坐标) |
ELEMENT | 图形(譬如点图)及其视觉属性(譬如color) |
GUIDE | 辅助元素(譬如legend) |
生成一个统计图形的步骤如下图所示:
从数据到统计图形
那么,基于图形语法画一个饼图的过程是怎么样的?拿 JavaScript 版本的图形语法 G2 举例,代码如下:
G2 画饼图的过程
const data = [
{ k: '一', v: 40 },
{ k: '二', v: 21 },
{ k: '三', v: 17 },
{ k: '四', v: 13 },
{ k: '五', v: 9 }
]
const dv = new DataSet.View().source(data) // 载入数据
.transform({ // 数据处理:统计每一个 key 对应数值 value 占总和的比例
type: 'percent',
field: 'v',
dimension: 'k',
as: 'percent'
})
const chart = new G2.Chart({
container: 'id' // 指定图表容器,可以是 DomNode,也可以是 id
})
chart.source(dv) // 载入数据
chart.axis(false) // 不显示坐标轴
chart.coord('polar').transpose() // 坐标转换
chart.intervalStack() // interval 类型的 element,做堆叠处理
.position('1*percent') // 位置映射
.color('k') // 颜色映射
chart.render() // 渲染图表
和传统枚举图表类型的可视化工具相比,基于图形语法的可视化工具的特征是:生成每一个图形的过程就是组合不同的基础图形语法的过程。上述饼图的生成过程就经历了从原始数据 data 到数据转换、坐标轴转换、指定辅助元素、指定基础图形对象、度量转换、数据映射等过程。图形语法的灵活和强大之处就在于,我们只需要改动其中某一步的处理过程,就能得到完全不同的、全新的图表。譬如,上述代码只需改动坐标转换部分的语句,就能以下各种结果:
从左往右分别是:柱状图、条形图、牛眼图和饼图
直角坐标 | 直角坐标反转 | 极坐标 | 极坐标反转 |
.coord('rect') | .coord('rect') | .coord('polar') | .coord('polar') |
| | | |
而所有的语句都是可以改动和微调的,抽象出来的绘图过程每一个步骤都可以变换改动,从而产生无数种组合的图表。这正是图形语法的精髓之处,引用 ggplot2 作者的话来说,就是:
图形语法能让我们简洁地描述图形组件。这种语法能使我们超越命名图形(譬如散点图),更深入地理解统计图形的层次结构
通过图形语法,我们不仅能画出已知的几乎所有图表,更能组合创造出各式各样全新的图表来。
图形语法的开源实现
《The Grammar of Graphics》于1999年初版,2005年再版,至今已经有十多年历史。除了在各种商业系统(SPSS、Tableau等)中应用以外,开源社区也开始逐渐诞生各种版本。下面是几个比较典型的基于图形语法的开源实现。
ggplot2
ggplot2 是 R 语言社区最著名的可视化绘图包,2005年由 Hadley Wickham 创造。ggplot2 是目前开源社区图形语法特性实现最全面的软件,迄今已经成长为 R 社区乃至可视化业界最受欢迎的包之一。
Bokeh
Bokeh 是图形语法在 Python 技术栈下的实现。图形语法的实现是基于 Python 的,最终渲染是用 D3 在浏览器上绘图。其优势是可以借由 Python 获得大规模数据的处理能力,但也因为同时具备两个端(BS 架构),所以嵌入其他系统的成本相对较大。
Vega
Vega 是华盛顿大学计算机学院数据交互实验室(IDL)开发的一套交互图形语法,定义了数据到图形的映射规则、常见的交互语法和常见的图形元素,用户可以自由使用 Vega 语法进行组合构建出各种各样的图表。其语法格式是 JSON,渲染引擎是 D3,一定程度上参考了《The Grammar of Graphics》,并且在其基础上进行了“用语法定义交互流程和行为”方面的探索。
AntV-G2
G2 是一套基于可视化编码的图形语法,开源来自蚂蚁金服数据可视化团队,是蚂蚁金服数据可视化解决方案 AntV的重要组成部分。以数据驱动,具有高度的易用性和扩展性,用户无需关注各种繁琐的实现细节,一条语句即可构建出各种各样可交互的统计图表。G2 是目前 JavaScript 社区对《The Grammar of Graphics》还原度最高的实现,刚一开源就得到 Leland Wilkinson 本人的肯定。除实现“图形语法”部分以外,G2 还针对 JavaScript 技术栈在“数据驱动”和“交互”方面进行探索,愿景是实现一套“数据驱动的高交互可视化图形语法”。
未完待续
关于 G2,AntV 更多见 AntV-返璞归真幻化万千可视化表达
by 蚂蚁金服数据可视化团队,绝云 & 御术·林峰