大数据可视分析方法与应用
上QQ阅读APP看本书,新人免费读10天
设备和账号都新为新人

1.3 实例1——VisComposer:可视化图表制作工具

可视化的需求日益巨大,这对可视化工作者们来说既是机遇也是挑战。如何规范化地进行可视化系统开发,提高开发和管理效率,是可视化工作者们所关心的问题。可视化系统开发不仅涉及可视化设计流程,还跟软件工程的软件开发流程密切相关。为了提高可视化系统开发的效率,作者主导开发了一个基于嵌套增量模型的交互式的可视化设计工具VisComposer。VisComposer从软件工程的角度出发,提出针对可视化系统开发的嵌套增量模型,帮助和指导用户进行可视化系统开发。

VisComposer的特点如下:

①面向普通用户,提供简单易上手的图形界面,降低用户的使用门槛;

②使用组件化的思想,提供预定义的可视化组件,让用户通过组件之间的自由组合来完成样式更丰富的可视化设计;

③引导用户有效地对可视化系统进行解构,以及进行更加精确和细粒度的调参和修改,提供强大的数据处理能力和可视化表达能力;

④与嵌套增量模型紧密相关,有效帮助用户在嵌套增量模型的标准开发流程下进行可视化系统开发。

1.3.1 框架设计

VisComposer由组件库、场景树、变换工作流和渲染器四大模块组成,如图1-4所示。组件库提供了多种组件,供用户完成各种任务;场景树负责维护图元组件的结构抽象;变换工作流则处理场景树节点的数据变换和可视映射;最后由渲染器解析整个场景树,并完成绘制。下面将详细介绍每个模块的设计和实现。

图1-4 VisComposer可视化设计模型由四大模块构成

1.3.1.1 组件库

很多可视化设计工具会采用模板化的方式帮助用户制作可视化视图,用户只需将数据导入到模板中并设置好维度绑定就能生成视图。而VisComposer则选用了一种更加灵活的方式——组件化。用户能通过不同组件的自由组合,定制出不同的可视化视图。系统提供的预定义组件主要包括以下四类。

①数据集:支持CSV或JSON格式的数据文件,同时支持用户本地上传数据和服务端存储用户数据。用户直接在界面上通过交互上传、查看和使用系统中的数据集。

②可视化元素:提供多种常用的图元组件(如圆、矩形、扇形)和布局组件(如笛卡儿坐标系、矩阵、极坐标系),供用户组成可视化图表。

③数据处理:系统提供多种常用的数据处理组件,涵盖了数据选取、排序、统计等功能。

④可视化模板:可视化模板组件采用JSON字符串的形式声明式地保存可视化图表模板,包括一些常用的图表(如散点图、柱状图、折线图等),用户只需接入自己的数据便可生成相应的可视化视图,也可根据需求在场景树模块和变换工作流模块对这些视图做出相应修改;另外,用户自己设计的可视化作品也能被保存成系统的可视化模板组件,然后用于分享和重用。

1.3.1.2 场景树

场景树模块是可视化的结构抽象,是可视化场景中所有图元的层次关系,特别地,在我们实现的基于SVG绘制的Web系统中,与最后的绘制结果的Dom结构一一对应。很多设计软件都采用场景树的形式来管理场景结构,如Adobe Photoshop的图层管理、3D Studio Max和Autodesk Maya的场景管理等。场景树模块能帮助用户梳理可视化视图的架构,自顶向下地完成可视化设计。

场景树采用树状结构,包括了节点和边两个部分。节点表示的是同一类图元,由用户从可视化元素组件库中选用并生成。特别地,每个场景树都默认带有根节点,根节点表示的是整块画布,其他节点则分成视图节点和图元节点两种:视图节点一定具有子节点,必须带有布局组件,用来指定子节点的排列方式;图元节点一般是叶子节点,不带布局组件但跟最终绘制的可视化图元一一对应。边表示的是视图与视图、视图与图元的包含关系,以及父节点向子节点分发数据和资源的过程。详细的逻辑会在后面章节中结合实例说明。

场景树的另外一个主要作用是支持用户对可视化设计的复用和保存。用户可以截取场景树中的任意子树选择保存,系统将以JSON字符串的形式做声明式的保存,并将其添加到组件库的可视化模板库中。当用户想再次生成该子树时,只需将其添加到任意的节点下,系统将自动解析JSON字符串中的信息,并生成场景树子树,用户只需接入相应的数据。

1.3.1.3 变换工作流

VisComposer采用变换工作流模块来管理和编辑场景树节点的数据和属性。变换工作流是一个比较自由的工作空间,在这个空间里,允许用户进行三种类型的操作:数据过滤、指定数据和图元的绑定。指定给所有子节点的输出数据。输入数据从其父节点传入,在变换工作流中用工作流输出端口表示。用户通过添加数据处理组件对数据进行选取、过滤、排序、统计等操作。随后再选取数据维度与视图或图元的视觉通道进行绑定。若节点有子节点,变换工作流中会列出所有的子节点,每个子节点由一个工作流输出端口表示,用户可将任意组件的输出数据派发到指定的子节点上,让这些数据在子节点中被可视化。

变换工作流中会维护一个组件列表,存储了该工作流中所有的组件,并通过唯一的标识符来标识。每个组件可以具有多个输入和多个输出,统称为端口,也都各有一个唯一的标识符。输入端口只能与其他组件的一个输出端口唯一连接,而输出端口则可以对应多个其他组件的输入端口。特别地,组件的输入输出端口还能与变换工作流输入端口和工作流输出端口连接,以接收该节点的父节点传入的数据以及将数据传递给子节点的变换工作流。组件间的连接关系表达的是数据在组件间的流动,数据从输入端口进来,经过组件内部的处理,再通过输出端口输出。整个变换工作流最终可以表述为工作空间中所有组件以及这些组件之间的拓扑序。

场景树中的每个节点有且仅有一个对应的变换工作流。父节点和子节点之间的变换工作流紧密联系,父节点直接派发数据给子节点,每个子节点得到父节点数据集的一个子集。每个变换工作流中会列出从父节点传下的数据以及该节点的所有子节点。每个节点的变换工作流都带有一些默认的组件,如可视映射组件等。特别地,视图节点的变换工作流中必须要添加布局组件。

1.3.1.4 渲染器

VisComposer配备了专门的渲染器,能解析用户创建场景树和变换工作流,并利用系统选定的绘制工具(如SVG或者Canvas)进行绘制。

图1-5的例子解释了渲染器解析场景树和变换工作流的原理。图1-5(a)中的场景图含有两层三个节点,渲染器会将这三个节点分别解析为三个函数:FuncA、FuncB、FuncC。假设输入数据为data,场景树的渲染流程可以表示为对树的深度优先遍历,并依次执行每个节点的函数:FuncA(data);FuncB[FuncA(data)];FuncC[FuncA(data)]。同样地,在图1-5(b)中,变换工作流中的组件都会被解析为函数,并按照组件之间连接的拓扑序依次执行每个组件的函数,最终得出绘制结果。

图1-5 场景图和变换工作流示例图

渲染器还会提供与场景树、变换工作流等窗口并列的绘制结果窗口,提供实时的设计结果绘制展示,每当用户对场景树或变换工作流中的任何属性进行编辑时,绘制结果都会快速地进行实时更新。同样,绘制结果上带有一些默认的选中和平移交互,用户可以直接在绘制结果上操作,渲染器会将同等意义的属性修改同步到场景树和变换工作流的相应模块上。

1.3.2 与嵌套增量模型的关系

VisComposer系统与嵌套增量模型的关系在于:它帮助用户在嵌套增量模型的标准开发流程下进行可视化系统开发。首先,组件库模块体现了对可视化系统进行解构的思想,用户将完整的可视化系统拆分成若干个增量构件,并保存为组件库中的组件,每个增量构件/组件的开发互相独立、并行开发;其次,场景树模块将不同的增量构件组织在一起,组成完整的可视化系统;再次,变换工作流模块帮助用户完成可视化设计流程中的数据处理和可视化映射与交互两个步骤的工作,并能进行精确的、细粒度的属性参数调整,渲染器模块则完成可视化渲染的工作。可以说,用户使用VisComposer工具开发可视化系统的过程,就是基于嵌套增量模型开发的过程。

1.3.3 系统实现

VisComposer系统界面如图1-6所示。系统主要分为组件库窗口、场景树窗口、变换工作流窗口和视图绘制窗口。所有窗口小部件和视图都设计为可折叠,以便为主视图保留更多的屏幕空间。用户通过简单的交互方式,用系统提供的各类组件,就可以不用编写任何代码,创建出各种可视化视图。

图1-6 VisComposer工具界面截图,(a)、(b)、(c)、(d)分别为系统的组件库窗口、变换工作流窗口、场景树窗口和视图绘制窗口

系统开发的技术栈如图1-7所示。前端用到了Javascript的工具库jQuery.js、SVG绘制库D3.js和前端UI组件库jQuery UI;后端则用node.js的Express框架实现,负责处理用户的上传数据集、数据集读取和可视化模板保存等操作,通过RESTful接口暴露给前端调用。

图1-7 VisComposer系统开发的技术栈

本章接下来的小节将介绍四个窗口的详细界面和功能设计。

1.3.3.1 组件库窗口

前文介绍了四大类组件,包括数据集、可视化元素、数据处理和可视化模板。在VisComposer系统中,这些组件以图标的方式分类存放在组件库窗口中,用户直接双击或拖拽到场景树窗口或变换工作流窗口使用。

图1-6(a)部分展示了系统提供的一些预定义组件窗口。可视化模板(Form)部分提供了散点图、折线图、柱状图、堆叠图、矩阵、平行坐标等12种可视化模板,用户使用可视化模板组件时,直接将选用的可视化形式对应的图表拖到场景图窗口的任意节点,就会生成新的子树,用户再在该子树的根节点指定好输入数据即可使用。

图元(Primitive)部分提供了包括圆、矩形、多边形、路径、扇形、文字等12种图元,这些图元的视觉通道都已预先设定好,用户可以在变换工作流中通过连线的方式直接将数据绑定到某个视觉通道上。

另外,布局(Composition)部分提供了水平排列、垂直排列、直角坐标系、矩阵排列等8种布局;数据变换部分提供了数据维度选取、数据过滤、排序、数学运算等10种运算器。所有类型的组件都可以任意地扩充,特别是可视化模板组件,可直接由用户从自己的设计中保存成模板。

VisComposer的组件库还包括数据集组件库。图1-8展示的是用户使用数据组件库窗口上传数据。系统支持用户从本地上传CSV和JSON格式的文件,CSV数据在上传前需用户先确认每个维度的数据属性,数据集窗口列出的数据可以查看维度和详细数据。每个数据集同样是通过拖拽交互将数据导入到任意节点的工作流中。

图1-8 CSV数据在上传前需要用户确认每个维度的数据属性

1.3.3.2 场景树窗口

场景树窗口给用户提供了创建场景树的界面,用户可执行的操作包括添加/删除场景树节点、编辑节点属性、选定节点编辑变换工作流和将任意子树保存成可视化模板等。

图1-9展示的是一个简单的散点图的场景树结构。CANVAS节点是场景树的根节点,表示成一张二维平面上的画布,用户可以直接在节点上编辑画布的长、宽和背景色;Scatterplot节点属于视图节点,含有笛卡儿坐标系布局组件,以二维直角坐标系的形式布局其含有的图元;Circle节点是图元节点,也是场景树的叶子节点。

图1-9 一个简单的例子:散点图的场景树结构

从图1-9还能看到,一个150行的表格数据从Scatterplot节点导入,按行分发给下一层节点Circle,Circle节点对应数据的行数自动生成了150个圆图元。

图1-9还展示了如何将场景树中任意子树保存成可视化模板:用户只需在任意节点处右键点击,即可看到“save as templates”选项,点击过后组件库窗口会新增一个可视化模板组件,表示该节点以及其子树已经成功地保存成模板。

用户在场景树窗口通过点选节点来编辑该节点的变换工作流。变换工作流窗口显示的工作空间总是场景树窗口中选中节点的变换工作流。

1.3.3.3 变换工作流窗口

变换工作流窗口是VisComposer系统的核心,用户在场景树搭好了可视化场景的框架之后,需要在每个节点内指定好数据输入、数据变换、可视映射还有对子节点的输出,这些操作都在变换工作流窗口完成。

基于前文提出的模型,VisComposer系统实现了图1-10中的变换工作流窗口,图中展示的变换工作流对应的是图1-9的散点图场景树的Scatterplot节点。

图1-10 图1-9中Scatterplot节点的变换工作流

从图1-10中可以看到,变换工作流本身有输入和输出,输入区域a允许导入数据或者接收父节点传下来的数据;输出区域b则列出自己所有的子节点,因为Scatterplot节点只有Circle一个子节点,所以图中变换工作流的输出只有一个Circle,任意的数据可以直接以连线的方式连进来,传到Circle节点。b、c、d是三个组件,其中b是数据集组件,c是直角坐标系的布局组件,而d是对应视图节点的图元组件,用来编辑视图的大小和位置等属性。

变换工作流的输入、组件和变换工作流的输出通过端口之间的连接线组织在一起。

1.3.3.4 视图窗口

视图窗口用来展示可视化最终的绘制结果。图1-11展示的是图1-9场景树对应的绘制结果。系统采用D3.js作绘制工具,最终渲染成SVG的DOM节点,如图1-11右下角所示,DOM节点的层次结构与图1-9场景树相互呼应。

图1-11 视图窗口展示绘制好的散点图

用户能直接在视图上编辑视图或节点的属性。例如,用户对一个视图平移了一个(10,10)的位移,系统会自动将这个位移添加到该视图的变换工作流的视图组件中。

当用户用右键对图元进行点击时,会弹出一个菜单,其中第一个选项“apply new method”的意思是按照特定条件选取一组图元实体,并在原来节点的同一层拆出一个新节点,用户以这样的方式对选中的这组图元实体进行重新设计,比如替换成另外的图元形式等。散点图矩阵中会用到这个功能,因为该视图展示一个表格数据维度之间的关系,比如一个四个维度的数据,散点图矩阵会生成一个4×4的方阵散点图。然而,在正对角线上的散点图的点都是排成一条直线,因为它们分别表示每个维度自己与自己在二维坐标系下的关系。因此,一般会把这个对角线上的视图替换成直方图之类的统计图,展示该维度的值域分布。用户可直接在散点图矩阵上用“apply new method”功能将对角线四个散点图选出来生成新节点,然后将该节点的可视化形式改成堆叠图。图1-12显示了这几个交互操作的流程。

图1-12 将散点图矩阵对角线的散点图替换为堆叠图