什么是桑基图

Google 搜索桑基图,可以搜到一大堆定义。简而言之,桑基图是一种数据流图,展示了数据是如何从左到右流向最后的节点,每条边代表一条数据流,宽度代表数据流的大小。桑基图常用于流量分析,可以很清楚的看出数据是如何渐渐分流的。本文着重讲解如何实现,理论方面的东西各位可以自行了解。

实现桑基图的关键点

关键点有两个:

1. 坐标计算

桑基图要展现的数据流,算是图(拓扑类、网络型或关系型)数据的一种。实现一个数据可视化图,最重要的就是拆解元素。而实现一个图数据可视化,则最重要的是分清“节点”和“边”。

拆解元素之后,最重要的便是坐标的计算,这里包括点和边的坐标。而图形中,任何的元素都可以看作是点连线而成,所以元素坐标的计算实际上就成了点坐标的计算。比如桑基图中,节点是一个矩形,那么只需计算两个点(左上和右下)的坐标(x0, y0),(x1, y1)便可确定;边是一个带形,需要计算四个端点才能确定,带形的弧度则可由简单的三次贝塞尔曲线计算得来。

由此观之,实现桑基图的核心在于计算出以上的这些点坐标。其实实现任意一种可视化都是计算点的坐标。

2. 减少边交叉

当数据量到一定程度的时候, 桑基图中的边会出现重叠现象,造成一定的视觉混乱。如何减少可以阅读本文第二节。

一、坐标计算的实现

准备工作

设计数据结构

经典的图数据结构一般是邻接矩阵和邻接表,我们也可以自己设计。我在做拓扑数据可视化的时候,会先和后端或数据同学商定好我需要拿到的数据结构,通常是这个样子:

{

nodes: [

{ foo: bar },

{ foo: baz },

...

],

links: [

{ source: 0, target: 1, value: 100 },

{ source: 1, target: 2, value: 10 },

...

]

}

而我拿到之后要做的第一步就是先把 nodes 和 links 串联起来,这里每个 link 的 source 和 target 分别是 nodes 的下标,当然你也可以设置其他的引用(指针),总之通过引用讲两者串联起来,变成:

{

nodes: [

{

foo: bar,

column: 0, // 节点所在第几列

row: 0, // 节点所在第几行

value: 100, // 节点数据流大小

sourceLinks: [

{

source: 0,

target: 1,

...

}

],

targetLinks: [

...

]

},

...

],

links: [

{

source: 0,

target: 1,

value: 100,

sourceNode: {

foo: bar,

column: 0,

row: 0,

...

},

targetNode: {

...

}

},

...

]

}

这样,对于某个节点来说,可以直接用 O(1) 的时间复杂度访问到它的任意相邻节点。

计算节点数据流大小

这里的计算方法可自己定,通常是取该节点入边和出边的数据流大小之和的最小值。

计算节点所在行列

在桑基图的计算中,我们还需要进行一个关键的计算——计算节点在桑基图中的第几行第几列。

第几列的计算,即为节点在图中的深度计算:

入度为 0 的节点深度为 0,在第一列

出度为 0 的节点深度最大,在最后一列

其余节点的深度为他相连源节点的最大深度加 1

第几行的计算,涉及到排序的问题,通常某一列中的节点都是按节点数据流大小,从大到小排序。

节点坐标计算

刚才我们说过,坐标计算可以分为两部分:节点和边。其中,边的坐标位置依赖于节点的坐标,所以应该先计算节点坐标。

但在计算坐标之前,首先要明确一个问题:是否限定视图的宽高。这个问题引申出两种节点坐标的计算方式。

不限定视图宽高

如果不限定宽高,那么节点坐标的计算步骤很简单:

设置一个节点的宽度

设置节点的水平间距

从左至右,根据刚才计算出的节点所在第几列,计算出节点的横坐标(x0, x1),初始的 x0 为 0

设定一个比例尺函数(多大的数据流对应屏幕上的多少像素,通常是首先设定一个节点最小高度和一个节点最大高度,然后找出所有节点数据流的最小和最大值,映射成一个定义域为节点数据流大小,值域为节点高度的函数)

通过比例尺计算出节点高度

设置一个节点垂直间距

从上至下,根据刚才计算出的节点所在第几行,计算出节点的纵坐标 (y0, y1),初始的 y0 为 0

大致是这个思路,横坐标的计算取决于两个值,节点宽度和 节点水平间距;纵坐标的计算取决于 节点的数据流大小 和 节点垂直间距。

具体的计算代码,可根据你自己的数据结构来调整。

限定视图宽高

如果限定宽高,那么计算步骤需要换个思路:

节点的宽度和节点的水平间距需要根据节点的列数和视图宽度来计算,你可以自己手动调整也可以设计个算法来算

从左只有,根据节点宽度和节点水平间距,计算出节点横坐标

设定一个比例尺函数,计算出节点的高度

设置一个节点垂直间距

通过高斯-赛德尔迭代(Gauss–Seidel method)计算出纵坐标(大致的思路是,先根据前两步的数值算出一个初始节点坐标,如果总体布局超出视图的下界,则节点高度和节点垂直间距都按比例缩小(如 0.95),并同时上移 n 个像素,如果总体布局超出视图上界,则节点高度和垂直间距都按比例缩小,并同时下移 n 个像素,直到总体的桑基图布局适应一开始限定的视图宽高)

这个思路是 d3-sankey 的实现思路。如果你有限定视图宽高的需求,那么可以直接使用 d3-sankey。

边的坐标计算

只要确定了节点坐标,边的坐标可以根据它源节点和目标节点的坐标来算出:

对于一个节点,将它的出边和入边进行排序(排序方法通常是根据相连节点在第几行从上到下排,也可以通过一些其他排序方法减少边的交叉,具体在第二节介绍)

计算每个节点中单位数据流占节点高度的比例

根据出边入边的数据流大小,乘上一步计算出的比例,则可得到每条边左右两边的高度

从上到下,计算每条边的纵坐标

每条边四个端点的横坐标分别对应源节点和目标节点的横坐标

以上操作可以通过遍历每个 node 的 sourceLinks 和 targetLinks 来计算。得到边的四个端点以后,就可以算出三次贝塞尔曲线的控制点了:

二、如何减少交叉

通常要减少边的交叉,可以采用下面两种方法:

均值排序这个名字是我自己起的。。不过这个方法很实用有效。

对于每个源节点来说,都有相连的目标节点。这里的“均值”指的是所有相连目标节点所在行数的平均值(所有目标节点的行数相加,除以目标节点个数),这个平均值可以大致描述该节点每个出边的位置。每条出边都有这样一个值,这个值越小,则说明该出边要连接的目标节点的位置越靠上,反之越靠下。所以可根据这个值,从小到大排出出边在该节点上从上到下的位置。

三、具体项目中的交互

我参与的 UBA (User Behavior Analytics 内部项目) 项目中,正好用到了桑基图。除了上述的图形绘制之外,主要复杂的是交互。

如图所示,除了基本的 hover 交互之外,项目中主要还有

minimap 拖拽和刷选

主视图的拖拽和缩放

左下角的过滤器

点击交互,高亮只经过选中节点的路径,并且边上高亮的部分由最后一个选中节点懈怠的数据流值确定,其余部分半透明

整个桑基图实现下来发现绘制只是一些计算,交互才是更难抽象和处理的部分。

综上,桑基图是一个 展现数据流非常好用的视图,感兴趣的同学可以自己实现一个试试。除了我文章中这些基本的桑基图布局,你还可以试试其他变种,另外交互方面也可以突破刚才我提到的那些,比如我之前实现过点击节点进行折叠/展开的交互。总体来说可视化还是一个比较有意思的方向。

python 桑基图_数据可视化之 Sankey 桑基图的实现相关推荐

  1. python 桑基图 地理坐标_【转载】Python数据可视化-实现Sankey桑基图

    根据不完整统计,90%想用sankey图的朋友都是因为被它炫酷的外表所吸引,举个例子: 在这里插入图片描述 关于sankey图的定义是这样描述的: 即桑基能量分流图,也叫桑基能量平衡图.它是一种特定类 ...

  2. 平均股价的时间序列图形_数据可视化——pandas绘制股票走势图

    python数据可视化工具除了matplotlib底层绘图包,还有在matplotlib基础上分装的seaborn绘图包,此外,数据分析报pandas也在matplotlib基础上分装内置了绘图功能. ...

  3. python图形界面实践_数据可视化之实践篇——python

    一.10个可视化例子 import matplotlib.pyplot as plt import seaborn as sns import numpy as np import pandas as ...

  4. python画误差图_Python数据可视化:如何创建误差图

    一图胜千言,使用Python的matplotlib库,可以快速创建高质量的图形. 这是Python数据可视化的系列短篇,针对初级和中级用户,将理论和示例代码相结合,使用matplotlib, seab ...

  5. python画图怎么调色_数据可视化Seaborn从零开始学习教程(二) 颜色调控篇

    作者:xiaoyu 微信公众号:Python数据科学 知乎:python数据分析师 Seaborn学习大纲 seaborn的学习内容主要包含以下几个部分: 风格管理 绘图风格设置 颜色风格设置 绘图方 ...

  6. 多维度雷达图怎么做_数据可视化:柱状图、雷达图等六种基本图表的特点和适用场合...

    序言 进入正题之前,先纠正一种误解. 有人觉得,基本图表太简单.太原始,不高端,不大气,因此追求更复杂的图表.但是,越简单的图表,越容易理解,而快速易懂地理解数据,不正是"数据可视化&quo ...

  7. r语言绘制精美pcoa图_R数据可视化4: PCA和PCoA图

    其实不论是PCoA还是PCA图均是用散点图来展示结果PCoA和PCA的结果,PCoA和PCA准确来讲是数据降维分析方法. 顺便值此佳节,祝福各位和"科研"都能够拥有幸福时光和美好结 ...

  8. python数据可视化书籍推荐_数据可视化的优秀入门书籍有哪些?

    数据可视化方向 首先你需要考虑清楚"非常感兴趣的数据可视化"属于哪一类? 数据可视化是个非常宽泛的领域,大体可以分为"信息图Infographic"和" ...

  9. python数据可视化例子各国人均寿命_数据可视化的16个经典案例

    [数据可视化] 本文编译自:Ross Crooks数据是非常强大的.当然,如果你能真正理解它想告诉你的内容,那它的强大之处就更能体现出来了. 什么是数据可视化? 数据可视化是指将数据以视觉的形式来呈现 ...

最新文章

  1. mysql file-pos_mysql-5.7 调整mysql的复制方式由master_log_file+master_log_pos 到gtid 详解
  2. 不简单的 SimpleDateFormat
  3. 从0到1学C++ 第3篇 从结构到类的演变
  4. 事务之五:Spring @Transactional工作原理
  5. 【WebRTC---入门篇】(十二)WebRTC传输协议
  6. 一图看懂软件缺陷检查涉及的内容
  7. php枚举属于什么类型,python枚举类型是什么?python枚举类型的简单介绍
  8. IIS7下 【请求被中止: 未能创建 SSL/TLS 安全通道 】 解决方法
  9. python下载numpy库_python怎么下载numpy
  10. 超好用的Redis管理及监控工具treeNMS
  11. iOS自动化测试元素定位
  12. 淘宝开放接口api分享
  13. 【转】 笔记本散热维护
  14. 携程线上测评测试题目,答案解析
  15. Java基础 -> 为什么⽤线程池?线程池的创建?
  16. windows server服务器打安全补丁
  17. 什么样的女人才是老婆(感动)
  18. snmp v3 参数_snmp v3的安全配置 snmp认证与加密配置(53)
  19. 【解决】grafana密码出现错误无法登录,强制进行密码修改
  20. shell之cut命令

热门文章

  1. elasticsearch5之Elastalert 安装使用 配置邮件报警和报警模版
  2. So easy!非技术人员也能学会的土狗防骗技巧!
  3. bert系列模型继续预训练(Pytorch)
  4. 前端对用户身份证号码进行验证以及模糊显示
  5. 人工智能医疗检测:微核细胞情况自动检出率可达90%
  6. 机器人视觉分析算法_机器视觉处理:目标检测和跟踪
  7. processing画正多边形
  8. 2022年中国版权保护中心计算机软件著作权登记最全申请步骤流程
  9. python 爬虫登录
  10. vue+elemnt ul 图片上传隐藏按钮+图片回显