桑基图最早出现在1898年,由美国工程师马修·亨利·菲利普斯·拉姆斯在一篇关于能源利用的科学论文中首次使用,他使用了这种图表来展示蒸汽引擎的能量损失情况,这个图表后来被称为桑基图
1. 桑基图作用
- 能源流向分析: 桑基图可以用来展示能源的产生、转换和消耗过程,有助于理解能源在系统中的分配情况和能源效率
- 材料流向分析: 在工业生产中,桑基图可以展示原材料的采购、加工和利用过程,帮助优化生产流程,提高资源利用效率
- 财务流向分析: 企业可以使用桑基图来展 示资金的流动情况,包括收入、支出、投资等,有助于管理财务风险和制定预算
- 环境影响评估: 桑基图也常用于分析环境系统中各种因素之间的相互关系,如排放源、污染物的迁移路径等 ,有助于评估环境影响和制定环境政策
- 信息流向分析: 在信息技术领域,桑基图可以用来展示数据流、网络流量等信息流向,帮助优化信息系统设计和网络架构
2. Python实现桑基图可视化
2.1 实现方法一
如图绘制2020东京奥运会金牌获奖数前五国家桑基图
import plotly.graph_objects as go
NODES = dict(
label=['美国', '中国', '日本', '英国', '俄罗斯', '金牌', '银牌', '铜牌'],
color=['#440154', '#482677', '#414487', '#355f8d', '#2a788e', '#e8c705', '#00a087', '#5f4a8b']
)
LINKS = dict(
source=[0, 0, 0, 1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4],
target=[5, 6, 7, 5, 6, 7, 5, 6, 7, 5, 6, 7, 5, 6, 7],
value=[39, 41, 33, 38, 32, 18, 27, 14, 17, 22, 21, 22, 20, 28, 23],
color = [
'lightgreen', 'lightgreen', 'lightgreen', # 节点0美国
'lightskyblue', 'lightskyblue', 'lightskyblue', # 节点1中国
'bisque', 'bisque', 'bisque', # 节点2日本
'lightcoral', 'lightcoral', 'lightcoral',# 节点3英国
'lightpink', 'lightpink', 'lightpink', # 节点4俄罗斯
]
)
data = go.Sankey(node=NODES, link=LINKS)
fig = go.Figure(data)
fig.update_layout(title='202东京奥运会奖牌榜前五', font_size=16)
fig.show()
可视化结果为交互性可通过鼠标悬停展示详细数据,使用 plotly 的 go.Sankey,该方法带有2 个参数 — nodes 和 links (节点和链接),其中所有节点—源和目标都应该有唯一的标识符,为方便理解用以下(唯一的)标识符、标签来标记这些节点:
美国-0 中国-1 日本-2 英国-3 俄罗斯-4
金牌-5 银牌-6 铜牌-7
9 10 11行代码意义:为0(美国)至5(金牌)6(银牌)7(铜牌)数量分别为39, 41, 33
后面 类似, 总共有15个链接依次表示出来
如果需要在奖牌后面添加上属于五常国家的奖牌数量只要加入新的源和目标就好,在这里为了美观对可视化指定了颜色,如果不指定将使用默认颜色
import plotly.graph_objects as go
NODES = dict(
label=['美国', '中国', '日本', '英国', '俄罗斯', '金牌', '银牌', '铜牌', '五常国家', '非五常国家'],
color=['#440154', '#482677', '#414487', '#355f8d', '#2a788e', '#e8c705', '#00a087', '#5f4a8b', '#ff7f0e', '#1f77b4']
)
LINKS = dict(
source=[0, 0, 0, 1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5, 5, 6, 6, 7, 7],
target=[5, 6, 7, 5, 6, 7, 5, 6, 7, 5, 6, 7, 5, 6, 7, 8, 9, 8, 9, 8, 9],
value=[39, 41, 33, 38, 32, 18, 27, 14, 17, 22, 21, 22, 20, 28, 23, 119, 27, 122, 14, 96, 17],
color=[
'lightgreen', 'lightgreen', 'lightgreen', # 节点0美国
'lightskyblue', 'lightskyblue', 'lightskyblue', # 节点1中国
'bisque', 'bisque', 'bisque', # 节点2日本
'lightcoral', 'lightcoral', 'lightcoral', # 节点3英国
'lightpink', 'lightpink', 'lightpink', # 节点4俄罗斯
'lightgreen', 'lightgreen', # 节点5金牌
'lightskyblue', 'lightskyblue', # 节点6银牌
'bisque', 'bisque'# 节点7铜牌
]
)
data = go.Sankey(node=NODES, link=LINKS)
fig = go.Figure(data)
fig.update_layout(title='202东京奥运会奖牌榜前五', font_size=16)
fig.show()
2.2 实现方法二
import pandas as pd
df = pd.read_excel('可视化数据.xlsx')
df.head()
读取数据集进行桑基图绘制,该数据存在五个特征,从登船港口-客舱等级-性别-年龄-是否幸存 路径进行可视化绘制
df.groupby('登船港口')['客舱等级'].value\_counts().reset\_index(name='数据')
思路与方法一一致首先需要把每一个节点数据统计出来如上展示代码只统计了船港口-客舱等级数据,接下来根据登船港口-客舱等级-性别-年龄-是否幸存 路径进行全部统计,也就可以理解为 整理数据结构为:父类→子类→值
df1 = df.groupby('登船港口')['客舱等级'].value_counts().reset_index(name='数据')
df2 = df.groupby('客舱等级')['性别'].value_counts().reset_index(name='数据')
df3 = df.groupby('性别')['年龄'].value_counts().reset_index(name='数据')
df4 = df.groupby('年龄')['是否幸存'].value_counts().reset_index(name='数据')
df1.columns = ['父类', '子类', '数据']
df2.columns = ['父类', '子类', '数据']
df3.columns = ['父类', '子类', '数据']
df4.columns = ['父类', '子类', '数据']
data = pd.concat([df1, df2, df3, df4], ignore_index=True)
data
接下来生成节点数据
nodes = [{'name': 'c港口'}, {'name': 'q港口'}, {'name': 's港口'}] + [{'name': i} for i in data['子类'].unique()]
nodes
最后整理为数据从哪里流向哪里,值为多少
links = [{'source': i[0], 'target': i[1], 'value': i[2]} for i in data.values]
links
from pyecharts import options as opts
from pyecharts.charts import Sankey
Sankey = (
Sankey(init_opts=opts.InitOpts(width="800px", height="600px", theme='vintage'))
.add(
"",
nodes=nodes,
links=links,
linestyle_opt=opts.LineStyleOpts(opacity=0.5, curve=0.3, color="source"),
label_opts=opts.LabelOpts(position="top"),
)
.set_global_opts(title_opts=opts.TitleOpts(title="桑基图"))
.render('桑基图.html')
)
用了pyecharts 库来创建一个桑基图,并将其保存为 HTML 文件。首先,通过 Sankey() 函数创建了一个桑基图对象 Sankey,并通过 .add() 方法添加了节点和链接数据,节点数据用于定义图中的各个节点,链接数据用于定义节点之间的连线以及流量大小,其中修改主题:通过修改theme参数来更改图表的主题可以尝试其他可用的主题,如'light'、'dark'或'westeros'等,这里会发现年龄是随机分布并没有按照顺序进行排序,由于这是一个交互性可视化可以直接进行手动拖拽调整至合适分布
3 . 往期推荐
基于VMD分解的VMD-CNN-LSTM时间序列预测模型实现
基于VMD分解的VMD-LSTM时间序列预测模型实现,大力提升预测精度!
如果你对类似于这样的文章感兴趣。
欢迎关注、点赞、转发~