TL;DR
不论你是做技术、BI 或是科研,都或多或少接触过“数据可视化”,或者在广义范畴来说便是各类图表。如果总结演绎一下,各种图表库依照表白性和速度的差别次要分为三类:
- 第一类是可视化剖析工具如 Tableau、Excel、google sheets 等,你只须要简略的交互操作,比方抉择和拖拽,就可能从预设的图表库中疾速创立出图表,但相应地图表的自定义水平会受到较多的限度。
- 第二类是 OpenGL、Canvas 等绘图引擎提供了一系列 API,能够齐全依照你的须要来实现可视化成果,当然细粒度的管制也意味着须要十分精通可视化实践。
- 第三类则介于二者之间,在速度和表白性之前做了衡量,在不同畛域都有较好的实现,例如 R 语言的 ggplot2、python 的 bokeh、Tableau 的 VizQL、前端中 canvas 的 ECharts 等等。
如果在 Github 上搜寻 chart
关键词会发现有 8.2w 个后果,其中有 3.3w 是与前端相干的,当然次要起因是浏览器的可视化应用起来更不便,也更容易分享。但如果工夫倒退会十年前,前端能用的图表库大略只有 Highcharts 和 Adobe Flex,但像 ggplot2 这些经典的图表工具倒是始终十分稳固,次要起因一方面得益于数据可视化这门学科的倒退,另一方面则是 HTML5 的崛起。十年间大部分图表库的倒退都是基于申明式可视化语法的状态,不同的库针对速度与表白性做了不同水平的形象,以满足不同档次的用户需要。
那么问题也来了,尽管大量图表库的呈现升高了应用的门槛和壁垒,然而对于一个小白用户而言,面对一堆图表库,心田大略就是“我是谁,我在哪,我该用哪个图表库”。如果是接手的我的项目可能曾经有明确的图表库了,比方国内大部分公司都会抉择 ECharts、BizCharts 或者 G2Plot,那么可能问题就变成了“这个图该怎么画呢”、“为什么这个配置不失效”、“版本要降级吗”等等一系列的问题。
当然,本文并不是来解决这些问题。能够预感,在前端这个后浪一直的畛域,新图表库依然会层出不穷的呈现,又或者接手的我的项目应用哪个图表库也不是马上能够被替换的。那么,了解外围的图形语法,能力以不变应万变。即便上手新的图表库,对着文档马上就能一把梭(前提是文档更新及时)。
图形语法
起源
图表作为数据可视化的重要载体,各类统计图表的形容和绘制,有着十分松软的实践根底,而且是数学形容的形式化零碎,这就是《The Grammar of Graphics》的内容。这本书十分好地体现了“思维形象”,咱们都晓得 Excel 的图表是如何抉择的:
又或者是 ECharts 的图表抉择:
显然,这种逐个列举的形式是一种低层次的形象。如果依照这种形式来绘制图表库,每减少一种新的图表,就须要减少一份绘图逻辑。一旦需要产生了大的变动,这个保护工作的难度可想而知。
Leland Wilkinson 在上世纪 80 年代开发 SYSTAT 的统计图形软件包时,也遇到了这个问题。最后的版本是枚举每一个已知的统计图形,最终代码量十分大。起初他基于面向对象的思路重构了这个我的项目,以一种树形构造治理图形元素,失去了更易扩大和动静的后果。图形语法正是在这个过程中编写的。
根本构造
Wilkinson 认为图形结构分为三个步骤,标准定义(Specification)、组装(Assembly)和显示(Display)。其中标准定义形容了如何将不同的图形对象“翻译”为形式化语言,由六局部组成:
- Data:数据,从数据集中创立变量的数据操作
- Trans:转换,数据变量之间的转换,例如排序
- Scale:标度,标度转换,例如 log 转换
- Coord:坐标,定义坐标零碎,例如极坐标
- Element:图形,及其视觉属性,例如点图和色彩
- Guide:参考,图形对象间的比拟、分类和对齐等,例如图例
组装则是依据标准定义绘制出画面,须要解决几何、布局、美学属性等等问题。展现则是指具体的显示枚举,如屏幕、纸张、视频等等,尽管咱们当初大部分场景下是在计算机相关的平台上展现。由此看来,标准定义是整个图形语法的根底。
视觉编码
Specification 中对于 Element 图形的形容,其实在 1967 年曾经有学者钻研过了。Bertin 在《Semiology of Graphics》一书中定量地论述了图形符号与信息之间的对应关系,奠定了可视化编码的实践根底。Bertin 认为视觉编码由两部组成,视觉标记(Visual Marks)和用于管制标记视觉特色的视觉通道。图形符号有点、线、面三种,视觉通道则分为地位变量和视觉变量(Visual Variables)。地位变量包含二维立体上 x 和 y 地位,视觉变量则包含尺寸 size_、明度 _value_、纹理 _texture_、色彩 _color_、方向 _orientation 和形态 _shape_。
依照 Bertin 所定义的视觉变量有 7 种,映射到图形符号点、线、面之后就有 21 种视觉编码,起初其他人又补充了一些视觉通道:长度、面积、体积、透明度、动画等,所以可用的视觉通道十分多。但个别一个可视化视图用到视觉通道并不是越多越好,视觉通道的重叠会造成视觉的凌乱。因而一份好的可视化设计须要思考到人类的感知力和认知力,以确保用户能够精确、无效地了解信息。不同视觉通道的优先级、实用的数据类型等也都是须要思考的。(这个命题波及到了可视化设计准则,在此就不开展了)。
劣势
图形语法把图形形象为可枚举的根本元素,并且能够 相互组合 生成更简单的元素。下图是 Data Points 对不同视觉编码在不同坐标系下总结。比方无填充的雷达图,其实就是把一般的折线图画在了极坐标系里。
尽管这种正交特色组合思维会存在一些不紧密的中央,然而其灵活性也是显而易见的,生成每个图形的过程就是组合不同的根底图形元素的过程,只须要改变其中某一步的处理过程,就能失去不同的可视化图表。应用这种语法结构,在实现一个绘图零碎时,能够大幅简化架构的设计,不仅能够形容罕用的已知图表,也能形容没有被宽泛应用(甚至还未创造)的图表。
举个例子
这个图被称为“子弹图”(Bullet Chart),子弹图无润饰地线性表达方式可能在狭小的空间中表白丰盛的数据信息。上图反映的是销售状况。彩色柱子的长度反映理论利润,背景色彩则是不同利润的区间范畴,红色线则为设定的指标,反映其是否实现指标。
如果依照传统的二维统计图表分类,子弹图并不是常见的柱状图或直方图,也很难归类。然而如果利用图形语法的思维,子弹图的形式化语言形容是这样的。元素 Element 有彩色柱形和红色标记,辅助 Guide 则是背景色彩灰度不同所代表的评估规范。
ELEMENT: rect(position(actual), color(black))
ELEMENT: tick(position(object), color(red))
GUIDE: rect(position(ranges), color.gray())
GUIDE: axis(dim(1), label(title))
形式化零碎
如果从技术角度而言,这本书所说的“图形定义”看起来也不离奇,无非是基于面向对象的思维。但作为学术著作,它的厉害之处是应用了“形式化零碎”来形容这套语法,说白了就是应用数学符号进行定义、演绎推理和验证。这本书中都是这么来定义的:
error bar 的定义
形容 nest 的时候书用的汇合定义
因为 Wilkinson 是个统计学家,在数学家的世界里只有数学的语言足够精炼和谨严。从抽象层次的角度,这个就比枚举、或是文言形容就高了很多。一方面各种定义、形容都十分简短,并且足够紧密,另一方面,图表的后续倒退能够依附这套形式化语言进行更多的符号演算实现。
实现
图形语法目前曾经有了不少的实现,如结尾提到的 ggplot2、vega、Bokeh、G2 等等。图形语法严格来说是一种思维,并不是一个真正意义上的实现规范,所以这些实现并不能相互兼容,有些实现为了兼顾理论的应用场景,也没有齐全遵循图形语法的原始定义。
在这些实现的根底之上,便是各类图表库。图形语法的形象水平这么高,小白用户没点可视化根底基本拿不下。但目前为止,即便图形语法曾经把图表拆成了不同的根本元素组合,然而没有哪个构建工具会让用户本人决定视觉元素、绑定数据、抉择坐标系等等。Wilkinson 自己尽管也在 Tableau 麾下,但 Tableau 也还是用“列举”的形式,提供一系列预设的“图表类型”来给用户抉择。
G2
再如 G2,也是打着“图形语法”的旗号。G2 中看似诡异的写法 chart.interval().position('genre*sold')
就是来自图形语法,这里的 * 不是乘法,而是作者本人定义的一种操作符,示意合并。但因为 JavaScript 不反对操作符重载,导致这里只能用字符串,失落了类型信息,很容易拼错了都不晓得。
G2 相较于拿来间接用的图表库更低一层,其定位也不是对标 Echarts 的,对于想把它拿来当成 Echarts 来用的人就会感觉十分苦楚。所以 G2 起初又提供了更简化的 G2Plot,又或是封装为 React 版本的 BizCharts 都从侧面验证了这一点。
Vega
另外值得一提的是 Vega,Vega 是基于 D3 实现的申明式可视化语法框架,和 D3 一样都出自华盛顿大学的 IDL 实验室。Vega 的指标是做数据可视化的配置语法,能够算是图表库的低代码。尽管 ECharts 等图表库也次要依附于 options/ config 等配置项,然而仍依赖于 JavaScript 代码来加载数据,然而 Vega 能够做到只须要 JSON 就能实现图表相干的开发,包含数据加载、转换等等。
例如上面的例子实现了加载一个 CSV 文件,并新增计算字段 temp_range,在 G2 的 Dataset 中也能够做到相似操作,但都是通过 JS 代码实现的,而 Vega 的底层引擎能够做到:
{"data": {"url": "data/seattle-weather.csv"},
"transform": [{"calculate": "datum.temp_max - datum.temp_min", "as": "temp_range"}
]
}
Vega 的配置化做法的益处,是特地不便程序生成和剖析,比方他们专门给 Python 开发的 Altair,原理就是动静生成 JSON 的 Vega 配置,因而很容易移植到其余语言。同时在穿插畛域(如机器学习与可视化的联合),这种低代码的模式更容易解决数据集。
然而谋求齐全的可配置性,导致最根本的图表都要写很多,比方上面是实现一个最简略的柱状图,都须要指定 scale、axies 等配置。所以 IDL 本人又在此基础上做了一个更高级的语法 Vega-Lite,基本上只有指定可视化标记类型、图形属性和数据字段的映射关系就可能实现一个图表。
Vega 的背地是个学术组织,所以相比拟来说更关注学术方面的倒退,一些在业界重要但没什么钻研价值的货色就不太关系,比方主题配色、动画、暗影等等的优先级很低。像动画在 2016 年就说要做了,而作者在前阵子又说有好多其余性能要做,动画这个先交给我的学生去钻研了╮(╯▽╰)╭
总结
本文次要十分浅显的介绍了图形语法(因为我也啃不动《The Grammar of Graphics》这本书),只是心愿大家对这些概念有一些理解,再去看各类图表库的设计也都基本上围绕着这些概念开展的。同时这本书的出发点也是十分值得咱们学习的,即抽象化的思考。
参考
- The Grammar of Graphics
- Semiology of Graphics
- Data Points
- 聊下图形语法“The Grammar of Graphics”
- 数据可视化图形语法简史
文章可随便转载,但请保留此 [原文链接]()。
十分欢送有激情的你退出 ES2049 Studio,简历请发送至 caijun.hcj@alibaba-inc.com。>