当前位置:

首页 > 编程开发 > Python 绘制桑基图教程,让你轻松打造惊艳数据可视化!

Python 绘制桑基图教程,让你轻松打造惊艳数据可视化!

桑基图简介很多时候,我们需要一种必须可视化数据如何在实体之间流动的情况。例如,以居民如何从一个国家迁移到另一个国家为例。这里演示了有多少居民从英格兰迁移到北爱尔兰、苏格兰和威尔士。从这个桑基图(Sankey)可视化中可以明显看出,从England迁移到Wales的居民多于从Scotland或NorthernIreland迁移的居民。什么是桑基图?桑基图通常描绘从一个实体(或节点)到另一个实体(或节点)的数据流。数据流向的实体被称为节点,数据流起源的节点是源节点(例如左侧的England),流结束的

本文目录

    桑基图简介

    很多时候,我们需要一种必须可视化数据如何在实体之间流动的情况。例如,以居民如何从一个国家迁移到另一个国家为例。这里演示了有多少居民从英格兰迁移到北爱尔兰、苏格兰和威尔士。

    Python 绘制桑基图教程,让你轻松打造惊艳数据可视化!

    从这个 桑基图 (Sankey)可视化中可以明显看出,从England迁移到Wales的居民多于从Scotland或Northern Ireland迁移的居民。

    什么是桑基图?

    桑基图通常描绘 从一个实体(或节点)到另一个实体(或节点)的数据流。

    数据流向的实体被称为节点,数据流起源的节点是源节点(例如左侧的England),流结束的节点是 目标节点(例如右侧的Wales)。源节点和目标节点通常表示为带有标签的矩形。

    流动本身由直线或曲线路径表示,称为链接。流/链接的宽度与流的量/数量成正比。在上面的例子中,从英格兰到威尔士的流动(即居民迁移)比从英格兰到苏格兰或北爱尔兰的流动(即居民迁移)更广泛(更多),表明迁移到威尔士的居民数量多于其他国家。

    桑基图可用于表示能量、金钱、成本的流动,以及任何具有流动概念的事物。

    米纳尔关于拿破仑入侵俄罗斯的经典图表可能是桑基图表最著名的例子。这种使用桑基图的可视化非常有效地显示了法国军队在前往俄罗斯和返回的途中是如何进步(或减少?)的。

    Python 绘制桑基图教程,让你轻松打造惊艳数据可视化!

    本文中,我们使用 python 的 plotly 绘制桑基图。

    如何绘制桑基图?

    本文使用 2021 年奥运会数据集绘制桑基图。该数据集包含有关奖牌总数的详细信息——国家、奖牌总数以及金牌、银牌和铜牌的单项总数。我们通过绘制一个桑基图来了解一个国家赢得的金牌、银牌和铜牌数。

    df_medals = pd.read_excel("data/Medals.xlsx")
    print(df_medals.info())
    df_medals.rename(columns={'Team/NOC':'Country', 'Total': 'Total Medals', 'Gold':'Gold Medals', 'Silver': 'Silver Medals', 'Bronze': 'Bronze Medals'}, inplace=True)
    df_medals.drop(columns=['Unnamed: 7','Unnamed: 8','Rank by Total'], inplace=True)
    
    df_medals
    
    RangeIndex: 93 entries, 0 to 92
    Data columns (total 9 columns):
     # Column Non-Null CountDtype
    --------- -------------------
     0 Rank 93 non-null int64
     1 Team/NOC 93 non-null object 
     2 Gold 93 non-null int64
     3 Silver 93 non-null int64
     4 Bronze 93 non-null int64
     5 Total93 non-null int64
     6 Rank by Total93 non-null int64
     7 Unnamed: 7 0 non-nullfloat64
     8 Unnamed: 8 1 non-nullfloat64
    dtypes: float64(2), int64(6), object(1)
    memory usage: 6.7+ KB
    None

    Python 绘制桑基图教程,让你轻松打造惊艳数据可视化!

    桑基图绘图基础

    使用 plotly 的 go.Sankey,该方法带有2 个参数 ——nodes 和 links (节点和链接)。

    注意:所有节点——源和目标都应该有唯一的标识符。

    在本文奥林匹克奖牌数据集情况中:

    Source是国家。将前 3 个国家(美国、中国和日本)视为源节点。用以下(唯一的)标识符、标签和颜色来标记这些源节点:

    • 0:美国:绿色
    • 1:中国:蓝色
    • 2:日本:橙色

    Target是金牌、银牌或铜牌。用以下(唯一的)标识符、标签和颜色来标记这些目标节点:

    • 3:金牌:金色
    • 4:银牌:银色
    • 5:铜牌:棕色

    Link(源节点和目标节点之间)是每种类型奖牌的数量。在每个源中有3个链接,每个链接都以目标结尾——金牌、银牌和铜牌。所以总共有9个链接。每个环节的宽度应为金牌、银牌和铜牌的数量。用以下源标记这些链接到目标、值和颜色:

    • 0 (美国) 至 3,4,5 : 39, 41, 33
    • 1 (中国) 至 3,4,5 : 38, 32, 18
    • 2 (日本) 至 3,4,5 : 27, 14, 17

    需要实例化 2 个 python dict 对象来表示

    • nodes (源和目标):标签和颜色作为单独的列表和
    • links:源节点、目标节点、值(宽度)和链接的颜色作为单独的列表

    并将其传递给plotly的 go.Sankey。

    列表的每个索引(标签、源、目标、值和颜色)分别对应一个节点或链接。

    NODES = dict( 
    # 0 1 23 4 5 
    label = ["United States of America", "People's Republic of China", "Japan", "Gold", "Silver", "Bronze"],
    color = ["seagreen", "dodgerblue", "orange", "gold", "silver", "brown" ],)
    LINKS = dict( 
    source = [0,0,0,1,1,1,2,2,2], # 链接的起点或源节点
    target = [3,4,5,3,4,5,3,4,5], # 链接的目的地或目标节点
    value =[ 39, 41, 33, 38, 32, 18, 27, 14, 17], # 链接的宽度(数量)
    # 链接的颜色
    # 目标节点: 3-Gold4-Silver5-Bronze
    color = [ 
    "lightgreen", "lightgreen", "lightgreen",# 源节点:0 - 美国 States of America
    "lightskyblue", "lightskyblue", "lightskyblue",# 源节点:1 - 中华人民共和国China
    "bisque", "bisque", "bisque"],)# 源节点:2 - 日本
    data = go.Sankey(node = NODES, link = LINKS)
    fig = go.Figure(data)
    fig.show()

    Python 绘制桑基图教程,让你轻松打造惊艳数据可视化!

    这是一个非常基本的桑基图。但是否注意到图表太宽并且银牌出现在金牌之前?

    接下来介绍如何调整节点的位置和宽度。

    调整节点位置和图表宽度

    为节点添加 x 和 y 位置以明确指定节点的位置。值应介于 0 和 1 之间。

    NODES = dict( 
    # 0 1 23 4 5 
    label = ["United States of America", "People's Republic of China", "Japan", "Gold", "Silver", "Bronze"],
    color = ["seagreen", "dodgerblue", "orange", "gold", "silver", "brown" ],)
    x = [ 0,0,0,0.5,0.5,0.5],
    y = [ 0,0.5,1,0.1,0.5,1],)
    data = go.Sankey(node = NODES, link = LINKS)
    fig = go.Figure(data)
    fig.update_layout(title="Olympics - 2021: Country &Medals",font_size=16)
    fig.show()

    于是得到了一个紧凑的桑基图:

    Python 绘制桑基图教程,让你轻松打造惊艳数据可视化!

    下面看看代码中传递的各种参数如何映射到图中的节点和链接。

    Python 绘制桑基图教程,让你轻松打造惊艳数据可视化!

    代码如何映射到桑基图

    添加有意义的悬停标签

    我们都知道plotly绘图是交互的,我们可以将鼠标悬停在节点和链接上以获取更多信息。

    Python 绘制桑基图教程,让你轻松打造惊艳数据可视化!

    带有默认悬停标签的桑基图

    当将鼠标悬停在图上,将会显示详细信息。悬停标签中显示的信息是默认文本:节点、节点名称、传入流数、传出流数和总值。

    例如:

    • 节点美国共获得11枚奖牌(=39金+41银+33铜)
    • 节点金牌共有104枚奖牌(=美国39枚,中国38枚,日本27枚)

    如果我们觉得这些标签太冗长了,我们可以对此进程改进。使用hovertemplate参数改进悬停标签的格式

    • 对于节点,由于hoverlabels 没有提供新信息,通过传递一个空hovertemplate = ""来去掉hoverlabel
    • 对于链接,可以使标签简洁,格式为-
    • 对于节点和链接,让我们使用后缀"Medals"显示值。例如 113 枚奖牌而不是 113 枚。这可以通过使用具有适当valueformat和valuesuffix的update_traces函数来实现。
    NODES = dict( 
    # 0 1 23 4 5
    label = ["United States of America", "People's Republic of China", "Japan", "Gold", "Silver", "Bronze"],
    color = ["seagreen", "dodgerblue","orange", "gold", "silver", "brown" ],
    x = [ 0,0, 0,0.5,0.5,0.5],
    y = [ 0,0.5, 1,0.1,0.5,1],
    hovertemplate=" ",)
    
    LINK_LABELS = []
    for country in ["USA","China","Japan"]:
    for medal in ["Gold","Silver","Bronze"]:
    LINK_LABELS.append(f"{country}-{medal}")
    LINKS = dict(source = [0,0,0,1,1,1,2,2,2], 
     # 链接的起点或源节点
     target = [3,4,5,3,4,5,3,4,5], 
     # 链接的目的地或目标节点
     value =[ 39, 41, 33, 38, 32, 18, 27, 14, 17], 
     # 链接的宽度(数量) 
     # 链接的颜色
     # 目标节点:3-Gold4 -Silver5-Bronze
     color = ["lightgreen", "lightgreen", "lightgreen", # 源节点:0 - 美国
    "lightskyblue", "lightskyblue", "lightskyblue", # 源节点:1 - 中国
    "bisque", "bisque", "bisque"],# 源节点:2 - 日本
     label = LINK_LABELS, 
     hovertemplate="%{label}",)
    
    data = go.Sankey(node = NODES, link = LINKS)
    fig = go.Figure(data)
    fig.update_layout(title="Olympics - 2021: Country &Medals",
    font_size=16, width=1200, height=500,)
    fig.update_traces(valueformat='3d', 
    valuesuffix='Medals', 
    selector=dict(type='sankey'))
    fig.update_layout(hoverlabel=dict(bgcolor="lightgray",
    font_size=16,
    font_family="Rockwell"))
    fig.show("png") #fig.show()

    Python 绘制桑基图教程,让你轻松打造惊艳数据可视化!

    带有改进的悬停标签的桑基图

    对多个节点和级别进行泛化相对于链接,节点被称为源和目标。作为一个链接目标的节点可以是另一个链接的源。

    该代码可以推广到处理数据集中的所有国家。

    还可以将图表扩展到另一个层次,以可视化各国的奖牌总数。

    NUM_COUNTRIES = 5
    X_POS, Y_POS = 0.5, 1/(NUM_COUNTRIES-1)
    NODE_COLORS = ["seagreen", "dodgerblue", "orange", "palevioletred", "darkcyan"]
    LINK_COLORS = ["lightgreen", "lightskyblue", "bisque", "pink", "lightcyan"]
    
    source = []
    node_x_pos, node_y_pos = [], []
    node_labels, node_colors = [], NODE_COLORS[0:NUM_COUNTRIES]
    link_labels, link_colors, link_values = [], [], [] 
    
    # 第一组链接和节点
    for i in range(NUM_COUNTRIES):
    source.extend([i]*3)
    node_x_pos.append(0.01)
    node_y_pos.append(round(i*Y_POS+0.01,2))
    country = df_medals['Country'][i]
    node_labels.append(country) 
    for medal in ["Gold", "Silver", "Bronze"]:
    link_labels.append(f"{country}-{medal}")
    link_values.append(df_medals[f"{medal} Medals"][i])
    link_colors.extend([LINK_COLORS[i]]*3)
    
    source_last = max(source)+1
    target = [ source_last, source_last+1, source_last+2] * NUM_COUNTRIES
    target_last = max(target)+1
    
    node_labels.extend(["Gold", "Silver", "Bronze"])
    node_colors.extend(["gold", "silver", "brown"])
    node_x_pos.extend([X_POS, X_POS, X_POS])
    node_y_pos.extend([0.01, 0.5, 1])
    
    # 最后一组链接和节点
    source.extend([ source_last, source_last+1, source_last+2])
    target.extend([target_last]*3)
    node_labels.extend(["Total Medals"])
    node_colors.extend(["grey"])
    node_x_pos.extend([X_POS+0.25])
    node_y_pos.extend([0.5])
    
    for medal in ["Gold","Silver","Bronze"]:
    link_labels.append(f"{medal}")
    link_values.append(df_medals[f"{medal} Medals"][:i+1].sum())
    link_colors.extend(["gold", "silver", "brown"])
    
    print("node_labels", node_labels)
    print("node_x_pos", node_x_pos); print("node_y_pos", node_y_pos)
    node_labels ['United States of America', "People's Republic of China", 
     'Japan', 'Great Britain', 'ROC', 'Gold', 'Silver', 
     'Bronze', 'Total Medals']
    node_x_pos [0.01, 0.01, 0.01, 0.01, 0.01, 0.5, 0.5, 0.5, 0.75]
    node_y_pos [0.01, 0.26, 0.51, 0.76, 1.01, 0.01, 0.5, 1, 0.5]
    # 显示的图
    NODES = dict(pad= 20, thickness = 20, 
     line = dict(color = "lightslategrey",
     width = 0.5),
     hovertemplate=" ",
     label = node_labels, 
     color = node_colors,
     x = node_x_pos, 
     y = node_y_pos, )
    LINKS = dict(source = source, 
     target = target, 
     value = link_values, 
     label = link_labels, 
     color = link_colors,
     hovertemplate="%{label}",)
    data = go.Sankey(arrangement='snap', 
     node = NODES, 
     link = LINKS)
    fig = go.Figure(data)
    fig.update_traces(valueformat='3d', 
    valuesuffix=' Medals', 
    selector=dict(type='sankey'))
    fig.update_layout(title="Olympics - 2021: Country &Medals",
    font_size=16,
    width=1200,
    height=500,)
    fig.update_layout(hoverlabel=dict(bgcolor="grey", 
    font_size=14, 
    font_family="Rockwell"))
    fig.show("png") 

    Python 绘制桑基图教程,让你轻松打造惊艳数据可视化!

    本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系bd@zhengruan.com
    作者最新文章
    编程开发 Python
    相关文章 更多
    python删除一个列表里的重复元素的方法与代码示例
    python删除一个列表里的重复元素的方法与代码示例

    学习如何使用Python高效删除列表中的重复元素。本文提供5种常见方法的代码示例,涵盖保持顺序与不保持顺序的场景,适合初学者和进阶开发者参考。

    Python写接口的步骤及完整代码示例
    Python写接口的步骤及完整代码示例

    详细讲解使用Python编写Web接口的核心步骤与完整代码示例,涵盖环境准备、路由定义、数据校验、服务启动及调试测试方法。

    codex怎么读取word文档及docx文件操作教程
    codex怎么读取word文档及docx文件操作教程

    介绍如何利用编程工具读取和解析Word文档(docx格式),涵盖基础文本提取代码示例、结构化数据处理逻辑,以及处理复杂排版时的技术局限与替代方案。

    怎么在Python中调用C语言代码提升性能
    怎么在Python中调用C语言代码提升性能

    详细讲解在Python中调用C语言代码提升性能的完整实践指南,包含原理分析、编译步骤、ctypes与CFFI具体实现、性能对比及常见陷阱。

    Python与C语言的性能差异及底层原理
    Python与C语言的性能差异及底层原理

    深入解析Python与C语言在执行效率上的数量级差异,从编译机制、变量内存布局、动态类型推断到GIL锁,系统阐明底层核心原理。

    Python和C语言哪个更适合编程入门
    Python和C语言哪个更适合编程入门

    客观对比Python与C语言在心智负担、底层机制与学习反馈上的核心差异,提供清晰有据的选择标准与切实的入门学习路径。

    selenium上传文件教程本地文件路径设置方法
    selenium上传文件教程本地文件路径设置方法

    深入解析Selenium处理文件上传的技术细节,涵盖标准HTML控件的路径直接注入法与非标准控件的系统级模拟方案,提供Windows与Linux环境下的路径设置最佳实践及常见异常排查。

    大数据开发语言选型:Java对比Scala与Python的优缺点及适用场景
    大数据开发语言选型:Java对比Scala与Python的优缺点及适用场景

    针对大数据工程场景,系统对比Java、Scala与Python在执行性能、生态结合、开发效率和维护成本上的核心差异,给出清晰的架构选型依据与落地方案。

    langgraph python guide中文入门教程详解
    langgraph python guide中文入门教程详解

    本篇LangGraph Python中文入门教程详解,系统梳理StateGraph状态机定义、节点编写、边与条件路由、检查点持久化(MemorySaver)等核心机制,提供从环境安装到完整循环智能体构建的代码示例与实操指导。

    Windows 安装 Python:从官方入口到虚拟环境的可复现实践
    Windows 安装 Python:从官方入口到虚拟环境的可复现实践

    面向后端开发者,基于 Python 官方文档说明如何在 Windows 上安装 Python、创建 venv 虚拟环境及使用 pip 管理依赖。包含可复制命令、验证方法及工具选择边界,避免常见配置误区。

    查看更多
    精品专题 更多
    装机必备
    装机必备

    正软商城装机必备专区,精选办公、浏览器、安全防护、影音播放、压缩解压、设计创作和系统工具等电脑常用正版软件,帮助用户快速完成新电脑软件配置。

    Windows
    Windows

    正软商城Windows软件专区,汇集适用于Windows电脑的办公、设计、安全防护、影音播放、开发工具和系统优化软件,提供软件介绍、系统要求、正版授权及购买下载服务。

    PDF教程
    PDF教程

    正软商城PDF教程频道提供PDF编辑、转换、合并、拆分、压缩及格式处理方法,同时介绍常用PDF软件和工具的使用技巧。

    Mac软件 更多
    讯飞智作 网页版
    讯飞智作 网页版
    Windows/ macOS/ Linux

    讯飞智作是一款基于语音合成技术、虚拟人驱动技术与数字人形象声音构建能力的 AI 数字人音视频创作平台。

    火山引擎 网页版
    火山引擎 网页版
    Windows/ macOS/ Linux

    火山引擎是字节跳动旗下企业级云与AI服务平台。聚焦大模型核心能力,依托字节自研豆包多模态大模型,凭借火山方舟一站式平台,提供模型精调、推理部署、智能应用搭建等全链路服务,结合高性能AI算力,助力各行业快速落地大模型数字化与智能化应用。

    Aperty macOS版
    Aperty macOS版
    macOS

    Aperty 是 Skylum 推出的 AI 人像修图软件,支持自然肤质修饰、瑕疵处理、面部与身体调整、预设及批量同步。

    WINDOWS 更多
    讯飞智作 网页版
    讯飞智作 网页版
    Windows/ macOS/ Linux

    讯飞智作是一款基于语音合成技术、虚拟人驱动技术与数字人形象声音构建能力的 AI 数字人音视频创作平台。

    火山引擎 网页版
    火山引擎 网页版
    Windows/ macOS/ Linux

    火山引擎是字节跳动旗下企业级云与AI服务平台。聚焦大模型核心能力,依托字节自研豆包多模态大模型,凭借火山方舟一站式平台,提供模型精调、推理部署、智能应用搭建等全链路服务,结合高性能AI算力,助力各行业快速落地大模型数字化与智能化应用。

    PixTV 网页版
    PixTV 网页版
    Windows

    PixTV 是一款在浏览器中使用的 AI 视觉内容创作平台,提供图片、视频、音频、文字生成、AI 分镜、局部重绘、提示词反推和无限画布等工具,适合短剧、漫剧、广告及社交媒体内容制作。