数据可视化-14. 桑基图
箭头的宽度表示流量的大小或比例,且同一颜色线条前后宽度一致,无论数据怎么流动,总数值保持不变,体现了数据的“能量守恒”。例如,在企业财务分析中,通过桑基图可以清晰地展示收入来源、支出类型以及盈利转化过程中的流向和占比,从而帮助企业发现利润来源、成本结构和资金回收的机会。通过可视化展示环境污染物的排放源、迁移路径和影响对象,可以更好地了解污染物的传播机制、评估环境风险,并制定相应的环境保护措施。通过
目录
1. 桑基图的概念
桑基图(Sankey diagram)即桑基能量分流图,也叫桑基能量平衡图,由瑞士(或爱尔兰,存在争议)工程师马修·桑基(Matthew Sankey)于1898年首次提出。
它是一种特定类型的流程图,通过一系列连续的箭头线段来表示数据在不同阶段或组件之间的流动和转移关系。箭头的宽度表示流量的大小或比例,且同一颜色线条前后宽度一致,无论数据怎么流动,总数值保持不变,体现了数据的“能量守恒”。
2. 桑基图的适用场景
桑基图适用于数据流动分析场景。
2.1 人口或者资源流动分析
它可以展示人口在不同地区和群体之间的流动情况。这对于城市规划、社会科学研究和人口统计分析等领域来说至关重要,有助于了解人口流动和迁移对城市规模、资源配置、就业机会等方面的影响。同样,它能够清晰地展示不同资源或者能源来源之间的关系以及能源的消耗与产出情况。这有助于评估不同能源的效率和可持续性,制定能源政策,并优化能源供应链。
2.2 产品供应链分析
它可以展示产品供应链的各个环节之间的关系和交互流量。通过跟踪原材料的来源、制造过程中的变化和消耗,以及最终产品的分发和销售情况,企业可以洞察供应链中的瓶颈和改进潜力。
2.3 电信通信或者网络流量分析
它在运营商、网络规划、互联网服务提供商等领域中,可用于展示网络通信中的数据流量和传输路径。这有助于优化网络性能、解决瓶颈问题以及规划新的网络基础设施。
2.4 财务分析
它可用于展示财务数据之间的流动和交互。例如,在企业财务分析中,通过桑基图可以清晰地展示收入来源、支出类型以及盈利转化过程中的流向和占比,从而帮助企业发现利润来源、成本结构和资金回收的机会。
2.5 环境影响评估
它有助于分析环境影响评估中的因素之间的关系和交互。例如通过可视化展示环境污染物的排放源、迁移路径和影响对象,可以更好地了解污染物的传播机制、评估环境风险,并制定相应的环境保护措施。
3. 桑基图的局限性
3.1 数据复杂度限制
如果节点或流线过多,桑基图会变得杂乱,难以阅读,只适合展示流动型数据(来源-去向关系),对于其他数据类型并不合适。
3.2 难以精确表达数据
虽然流线宽度代表流量大小,但人眼不容易准确判断不同宽度的微小差异。桑基图通常强调相对关系而非绝对值,如果用户需要精确的数据,图形可能无法完全满足需求。
3.3 创建开销复杂
桑基图要求清晰定义的来源、去向和权重数据,数据预处理可能耗时。当然现在在 AI 工具的帮助下,这个局限性正逐渐消失。
3.4 缺乏动态交互
在静态展示中,用户可能无法深入探索图表中的细节。动态交互(如放大、过滤流线等)需要额外开发或支持。当节点间的关系复杂时,部分重要信息可能因为图形拥挤被掩盖。
3.5 对比性不足
桑基图通常是单一场景的快照,难以直接对比多个时间段或数据组的变化。如果要比较不同年份的能源流动,桑基图无法同时展示所有年份的变化趋势,需结合其他图表类型。
3.6 面积易误导用户
流线宽度不等于面积,但用户可能误解为面积代表数据量。同时节点和流线的位置安排对理解至关重要,布局不佳可能导致误解。例如:将主要流向放置在边缘可能会降低用户对其重要性的关注。
3.7 局限于宏观分析
桑基图适合展示宏观趋势,但在微观层面可能不够深入,难以解释细节或因果关系。
4. 桑基图的代码实现
4.1 Python 代码实现
import dash
from dash import html, dcc, Input, Output
import plotly.graph_objects as go
import dash_bootstrap_components as dbc
import numpy as np
import plotly.express as px
def create_complex_sankey():
"""
创建一个复杂的桑基图
返回桑基图图形对象
"""
# 示例数据
labels = ["能源", "电力", "运输", "工业", "住宅", "商业", "损失", "可再生", "化石燃料", "核能"]
sources = [0, 0, 0, 1, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6]
targets = [1, 2, 3, 4, 5, 6, 4, 5, 6, 7, 7, 8, 8, 9, 9, 7]
values = [8, 4, 2, 8, 4, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1]
# 创建桑基图
sankey_fig = go.Figure(data=[go.Sankey(
node=dict(
pad=15,
thickness=20,
line=dict(color="black", width=0.5),
label=labels,
color=["#FF9999", "#66B3FF", "#99FF99", "#FFCC99", "#FF6666", "#66FF66", "#6666FF", "#FF66FF", "#66FFFF", "#FFFF66"]
),
link=dict(
source=sources,
target=targets,
value=values,
color=["rgba(255, 153, 153, 0.6)", "rgba(102, 179, 255, 0.6)", "rgba(153, 255, 153, 0.6)", "rgba(255, 204, 153, 0.6)",
"rgba(255, 102, 102, 0.6)", "rgba(102, 255, 102, 0.6)", "rgba(102, 102, 255, 0.6)", "rgba(255, 102, 255, 0.6)",
"rgba(102, 255, 255, 0.6)", "rgba(255, 255, 102, 0.6)", "rgba(255, 153, 153, 0.6)", "rgba(102, 179, 255, 0.6)",
"rgba(153, 255, 153, 0.6)", "rgba(255, 204, 153, 0.6)", "rgba(255, 102, 102, 0.6)", "rgba(102, 255, 102, 0.6)"]
)
)])
# 更新布局
sankey_fig.update_layout(
title='复杂桑基图示例',
font_size=10,
template='plotly_white'
)
return sankey_fig
app = dash.Dash(__name__, external_stylesheets=[dbc.themes.BOOTSTRAP])
density_plots = create_density_plots()
app.layout = html.Div([
html.H3("桑基图展示", className="text-center mt-4 mb-3"),
dcc.Graph(figure=create_complex_sankey())
])
if __name__ == "__main__":
app.run_server(debug=True, port=8051)
4.2 桑基图效果展示
更多推荐
所有评论(0)