如何利用pyecharts绘制酷炫的桑基图?
发布日期:2021-06-30 22:51:46 浏览次数:3 分类:技术文章

本文共 11686 字,大约阅读时间需要 38 分钟。

什么是桑基图

桑基图(Sankey diagram),即桑基能量分流图,也叫桑基能量平衡图。它是一种特定类型的流程图,核心在于展示数据的流转,图中延伸的分支的宽度对应数据流量的大小,通常应用于能源、材料成分、金融等数据的可视化分析。因1898年Matthew Henry Phineas Riall Sankey绘制的"蒸汽机的能源效率图"而闻名,此后便以其名字命名为"桑基图"。(来源:百度)

“桑基图”的数据特点是由源数据,目标数据,流量值三个量组成,源数据与目标数据之间是流量带,流量值越大流量带越宽。流量带由源数据流向目标数据,因为能量守恒,所以源数据宽度和目标数据宽度相等。

经典的桑基图

1869年的minard图

Charles Minard是信息图表之父,他是信息图领域的创始者。这张图描绘的是拿破仑在1812到1813年进攻俄国的情况。它的背景是一个真实的地图,西边是波兰的边境,东边是莫斯科。图上那条主线的宽度代表拿破仑军队的人数,黄色表示进攻路线,黑色表示撤退的路线:他开始于42万人,在向莫斯科进军的过程中丧失了很多人,到达莫斯科时只剩下10万人,而最后从莫斯科活着返回的只剩下1万人。

当时,这种图还不叫桑基图,因为桑基图的命名三十年之后才出现,但这张图很清晰的展现了“法国士兵人数” 这个值的流量变化过程,一路打,一路死,42万人最后剩下1万人回家,看这图就知道那场战争是多么的惨烈了。

1898年的蒸汽的能源效率图

1898年,爱尔兰船长马修·亨利·菲尼亚斯·里亚尔·桑基(Matthew Henry Phineas Riall Sankey)使用了这种类型的图表展示了蒸汽的能源效率。与此同时,这个图也以船长的名字命名为“桑基图”。

法国公共管理部门的资金来源

这张桑基图(Sankey Diagram)厘清了法国公共管理部门的资金来源,以及他们是如何分配这些资金的。

最左边的支点代表了不同的资金来源,包括社会、个人税收等。这些资金在汇总到法国的四大公共管理部门后,被再分配到交通、环境保护、住房、教育、文化等各个领域。 在描述收支情况时,桑基图能帮你捋清每一笔金钱的走向。钱都来自哪里,花在哪里,在一张桑基图上都能一目了然。

2017,年度行程表

这张图是桑基图的一个变种,展示了2017年度的一个日常事务的分类与时间行程对应关系,桑基图清晰的展现了日常事务的那种密集、交叉与繁忙。

其他的各种典型桑基图

如何绘制一个桑基图?

绘制“桑基图”需要用到pyecharts库。

安装:

pip install pyecharts

官方地址:

https://github.com/pyecharts/pyecharts/

开源教程:

https://pyecharts.org/#/zh-cn/intro

代码基础框架如下:

from pyecharts.charts import Sankeyfrom pyecharts import options as optssankey = Sankey()sankey.add(series_name=''  # 桑基图的名字           , nodes=[]  # 配置有多少个结点           , links=[]  # 配置结点之间的信息流关系           , linestyle_opt=opts.LineStyleOpts()  # 线样式配置项           , label_opts=opts.LabelOpts()  # 标签配置项           , levels=[opts.SankeyLevelsOpts(), ...]  # 每一层节点配置           , node_align=''  # 对齐方式的配置           , orient=''  # 方向的配置           )sankey.render('sankey.html')  # 输出html文件

下面从华北电力大学的2020年分省招生计划中选择一些专业和省份来说明桑基图的绘制方法。

【例子】全部默认配置的桑基图

from pyecharts.charts import Sankeyfrom pyecharts import options as optsnodes = [    {
'name': '电气类'} , {
'name': '电子信息类'} , {
'name': '核工程类'} , {
'name': '管理科学与工程类'} , {
'name': '工商管理类'} , {
'name': '经济学类'} , {
'name': '水利类'} , {
'name': '北京'} , {
'name': '天津'} , {
'name': '河北'} , {
'name': '山西'} , {
'name': '内蒙古'}]links = [ {
'source': '北京', 'target': '电气类', 'value': 20} , {
'source': '北京', 'target': '电子信息类', 'value': 13} , {
'source': '北京', 'target': '核工程类', 'value': 6} , {
'source': '北京', 'target': '管理科学与工程类', 'value': 8} , {
'source': '北京', 'target': '工商管理类', 'value': 16} , {
'source': '北京', 'target': '经济学类', 'value': 6} , {
'source': '北京', 'target': '水利类', 'value': 2} , {
'source': '天津', 'target': '电气类', 'value': 11} , {
'source': '天津', 'target': '电子信息类', 'value': 4} , {
'source': '天津', 'target': '核工程类', 'value': 1} , {
'source': '天津', 'target': '管理科学与工程类', 'value': 2} , {
'source': '天津', 'target': '工商管理类', 'value': 6} , {
'source': '天津', 'target': '经济学类', 'value': 2} , {
'source': '天津', 'target': '水利类', 'value': 2} , {
'source': '河北', 'target': '电气类', 'value': 15} , {
'source': '河北', 'target': '电子信息类', 'value': 6} , {
'source': '河北', 'target': '核工程类', 'value': 5} , {
'source': '河北', 'target': '管理科学与工程类', 'value': 4} , {
'source': '河北', 'target': '工商管理类', 'value': 8} , {
'source': '河北', 'target': '经济学类', 'value': 2} , {
'source': '河北', 'target': '水利类', 'value': 2} , {
'source': '山西', 'target': '电气类', 'value': 15} , {
'source': '山西', 'target': '电子信息类', 'value': 9} , {
'source': '山西', 'target': '核工程类', 'value': 5} , {
'source': '山西', 'target': '管理科学与工程类', 'value': 6} , {
'source': '山西', 'target': '工商管理类', 'value': 8} , {
'source': '山西', 'target': '经济学类', 'value': 6} , {
'source': '山西', 'target': '水利类', 'value': 3} , {
'source': '内蒙古', 'target': '电气类', 'value': 13} , {
'source': '内蒙古', 'target': '电子信息类', 'value': 3} , {
'source': '内蒙古', 'target': '核工程类', 'value': 2} , {
'source': '内蒙古', 'target': '管理科学与工程类', 'value': 2} , {
'source': '内蒙古', 'target': '工商管理类', 'value': 4} , {
'source': '内蒙古', 'target': '经济学类', 'value': 2} , {
'source': '内蒙古', 'target': '水利类', 'value': 2}]

全部默认设置

sankey = Sankey()sankey.add(    series_name='2020年份省招生计划'    , nodes=nodes    , links=links)sankey.render('sankey.html')

得到的结果如下,可以看到格式相当不美观,接下来,我们看看怎么设置参数,使得图片更加好看。

【例子】信息流的格式配置(颜色、透明度、曲线程度)

https://pyecharts.org/#/zh-cn/series_options?id=linestyleopts%ef%bc%9a%e7%ba%bf%e6%a0%b7%e5%bc%8f%e9%85%8d%e7%bd%ae%e9%a1%b9

sankey = Sankey()sankey.add(    series_name='2020年份省招生计划'    , nodes=nodes    , links=links    , linestyle_opt=opts.LineStyleOpts(        opacity=0.2  ###透明度设置        , curve=0.5  ###信息流的曲线弯曲度设置        , color="source"  ##颜色设置,source表示使用节点的颜色    )  ##线条格式 ,设置所有线条的格式)sankey.render('sankey.html')

输出结果为如下,好看了许多,但是生源地和专业的字看不清楚,接下来继续配置标签。

【例子】标签的格式配置(大小、颜色、位置)

https://pyecharts.org/#/zh-cn/series_options?id=labelopts%ef%bc%9a%e6%a0%87%e7%ad%be%e9%85%8d%e7%bd%ae%e9%a1%b9

sankey = Sankey()sankey.add(    series_name='2020年份省招生计划'    , nodes=nodes    , links=links    , linestyle_opt=opts.LineStyleOpts(        opacity=0.2  ###透明度设置        , curve=0.5  ###信息流的曲线弯曲度设置        , color="source"  ##颜色设置,source表示使用节点的颜色    )  ##线条格式 ,设置所有线条的格式    , label_opts=opts.LabelOpts(        font_size=16        , position='right'    )  ##标签配置,具体参数详见opts.LabelOpts())sankey.render('sankey.html')

输出结果如下,美观了不少。

【例子】配置每一层节点的颜色

有时候需要将同一层节点的颜色配置为一致的,我们可以通过level参数逐层配置节点和信息流的格式。

nodes.extend(    [{
'name': '实验班'} , {
'name': '教改班'} ])links.extend( [{
'source': '电气类', 'target': '实验班', 'value': 20} , {
'source': '电气类', 'target': '教改班', 'value': 14} , {
'source': '电子信息类', 'target': '实验班', 'value': 7} , {
'source': '电子信息类', 'target': '教改班', 'value': 8} , {
'source': '核工程类', 'target': '实验班', 'value': 5} , {
'source': '核工程类', 'target': '教改班', 'value': 5} , {
'source': '管理科学与工程类', 'target': '实验班', 'value': 6} , {
'source': '管理科学与工程类', 'target': '教改班', 'value': 6} , {
'source': '工商管理类', 'target': '实验班', 'value': 10} , {
'source': '工商管理类', 'target': '教改班', 'value': 10} ])sankey = Sankey()sankey.add( series_name='2020年份省招生计划' , nodes=nodes , links=links , linestyle_opt=opts.LineStyleOpts( opacity=0.2 ###透明度设置 , curve=0.5 ###信息流的曲线弯曲度设置 , color="source" ##颜色设置,source表示使用节点的颜色 ) ##线条格式 ,设置所有线条的格式 , label_opts=opts.LabelOpts( font_size=16 , position='right' ) ##标签配置,具体参数详见opts.LabelOpts() , levels=[ opts.SankeyLevelsOpts( depth=0, ##第一层的配置 itemstyle_opts=opts.ItemStyleOpts(color="#fbb4ae"), ##节点格式的配置 linestyle_opts=opts.LineStyleOpts(color="source", opacity=0.2, curve=0.5)) , opts.SankeyLevelsOpts( depth=1, ##第二层的配置 itemstyle_opts=opts.ItemStyleOpts(color="#b3cde3"), ##节点格式的配置 linestyle_opts=opts.LineStyleOpts(color="source", opacity=0.2, curve=0.5)) ##信息的配置 , opts.SankeyLevelsOpts( depth=2, ##第三层的配置 itemstyle_opts=opts.ItemStyleOpts(color="#ccebc5"), ##节点格式的配置 linestyle_opts=opts.LineStyleOpts(color="source", opacity=0.2, curve=0.5)) ##信息的配置 ] # 桑基图每一层的设置。可以逐层设置)sankey.render('sankey.html')

经济学类、水利类没有实验班和教改班,感官上不符合逻辑归类,于是我们进行“对齐方式”的设置。

【例子】对齐方式的配置

如果个别节点没有下级节点,其他的节点有下级节点,为了美观一些,可以选择节点对齐的方式。通过node_align参数进行配置。

桑基图中节点的对齐方式,默认是双端对齐,可以设置为左对齐或右对齐,对应的值分别是:

  • justify:节点双端对齐。
  • left:节点左对齐。
  • right:节点右对齐
sankey = Sankey()sankey.add(    series_name='2020年份省招生计划'    , nodes=nodes    , links=links    , node_align='left'    , linestyle_opt=opts.LineStyleOpts(        opacity=0.2  ###透明度设置        , curve=0.5  ###信息流的曲线弯曲度设置        , color="source"  ##颜色设置,source表示使用节点的颜色    )  ##线条格式 ,设置所有线条的格式    , label_opts=opts.LabelOpts(        font_size=16        , position='right'    )  ##标签配置,具体参数详见opts.LabelOpts()    , levels=[        opts.SankeyLevelsOpts(            depth=0,  ##第一层的配置            itemstyle_opts=opts.ItemStyleOpts(color="#fbb4ae"),  ##节点格式的配置            linestyle_opts=opts.LineStyleOpts(color="source", opacity=0.2, curve=0.5))        , opts.SankeyLevelsOpts(            depth=1,  ##第二层的配置            itemstyle_opts=opts.ItemStyleOpts(color="#b3cde3"),  ##节点格式的配置            linestyle_opts=opts.LineStyleOpts(color="source", opacity=0.2, curve=0.5))  ##信息的配置        , opts.SankeyLevelsOpts(            depth=2,  ##第三层的配置            itemstyle_opts=opts.ItemStyleOpts(color="#ccebc5"),  ##节点格式的配置            linestyle_opts=opts.LineStyleOpts(color="source", opacity=0.2, curve=0.5))  ##信息的配置    ]  # 桑基图每一层的设置。可以逐层设置)sankey.render('sankey.html')

【例子】方向的配置

有时候,流程比较长,横向展示不美观,竖向的桑基图会美观一些。

桑基图中节点的布局方向,可以是水平的从左往右,也可以是垂直的从上往下。

对应的参数值分别是horizontalvertical

通过orient参数来配置。

  • orient='horizontal':表示水平横向
  • orient='vertical':表示垂直竖向
sankey = Sankey()sankey.add(    series_name='2020年份省招生计划'    , nodes=nodes    , links=links    , node_align='left'    , orient='vertical'    , linestyle_opt=opts.LineStyleOpts(        opacity=0.2  ###透明度设置        , curve=0.5  ###信息流的曲线弯曲度设置        , color="source"  ##颜色设置,source表示使用节点的颜色    )  ##线条格式 ,设置所有线条的格式    , label_opts=opts.LabelOpts(        font_size=16        , position='bottom'    )  ##标签配置,具体参数详见opts.LabelOpts()    , levels=[        opts.SankeyLevelsOpts(            depth=0,  ##第一层的配置            itemstyle_opts=opts.ItemStyleOpts(color="#fbb4ae"),  ##节点格式的配置            linestyle_opts=opts.LineStyleOpts(color="source", opacity=0.2, curve=0.5))        , opts.SankeyLevelsOpts(            depth=1,  ##第二层的配置            itemstyle_opts=opts.ItemStyleOpts(color="#b3cde3"),  ##节点格式的配置            linestyle_opts=opts.LineStyleOpts(color="source", opacity=0.2, curve=0.5))  ##信息的配置        , opts.SankeyLevelsOpts(            depth=2,  ##第三层的配置            itemstyle_opts=opts.ItemStyleOpts(color="#ccebc5"),  ##节点格式的配置            linestyle_opts=opts.LineStyleOpts(color="source", opacity=0.2, curve=0.5))  ##信息的配置    ]  # 桑基图每一层的设置。可以逐层设置)sankey.render('sankey.html')

【例子】其他参数配置

  • is_selected=True:图例是否选中
  • pos_left='20%':图距离容器左边的距离
  • pos_top='20%':图距离容器上端的距离
  • pos_right='20%':图距离容器右侧的距离
  • pos_bottom='20%':图距离容器下端的距离
  • node_width=15:桑基图中每个矩形节点的宽度
  • node_gap=20:每一列两个桑基图之间的距离
  • is_draggable=True:是否能够拖动节点,默认拖动,可以不配置
sankey = Sankey()sankey.add(    series_name='2020年份省招生计划'    , nodes=nodes    , links=links    , node_align='left'    , orient='vertical'    , is_selected=True  # 图例是否选中    , pos_left='20%'  ##图距离容器左边的距离    , pos_top='20%'  ##图距离容器上端的距离    , pos_right='20%'  # 图距离容器右侧的距离    , pos_bottom='20%'  ###图距离容器下端的距离    , node_width=15  # 桑基图中每个矩形节点的宽度    , node_gap=20  # 每一列两个桑基图之间的距离    , is_draggable=True  ##是否能够拖动节点,默认拖动,可以不配置    , linestyle_opt=opts.LineStyleOpts(        opacity=0.2  ###透明度设置        , curve=0.5  ###信息流的曲线弯曲度设置        , color="source"  ##颜色设置,source表示使用节点的颜色    )  ##线条格式 ,设置所有线条的格式    , label_opts=opts.LabelOpts(        font_size=16        , position='bottom'    )  ##标签配置,具体参数详见opts.LabelOpts()    , levels=[        opts.SankeyLevelsOpts(            depth=0,  ##第一层的配置            itemstyle_opts=opts.ItemStyleOpts(color="#fbb4ae"),  ##节点格式的配置            linestyle_opts=opts.LineStyleOpts(color="source", opacity=0.2, curve=0.5))        , opts.SankeyLevelsOpts(            depth=1,  ##第二层的配置            itemstyle_opts=opts.ItemStyleOpts(color="#b3cde3"),  ##节点格式的配置            linestyle_opts=opts.LineStyleOpts(color="source", opacity=0.2, curve=0.5))  ##信息的配置        , opts.SankeyLevelsOpts(            depth=2,  ##第三层的配置            itemstyle_opts=opts.ItemStyleOpts(color="#ccebc5"),  ##节点格式的配置            linestyle_opts=opts.LineStyleOpts(color="source", opacity=0.2, curve=0.5))  ##信息的配置    ]  # 桑基图每一层的设置。可以逐层设置)sankey.render('sankey.html')

参考文献:

  • https://zhuanlan.zhihu.com/p/131373203

转载地址:https://lsgogroup.blog.csdn.net/article/details/117167096 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!

上一篇:王朝阳:河北高校邀请赛 -- 二手车交易价格预测决赛答辩
下一篇:黄家懿:河北高校邀请赛 -- 二手车交易价格预测决赛答辩

发表评论

最新留言

表示我来过!
[***.240.166.169]2024年04月06日 14时52分52秒