Python 绘制惊艳的桑基图,你学会了吗?(1)

上一篇 / 下一篇  2022-02-07 15:37:46

  桑基图简介
  很多时候,我们需要一种必须可视化数据如何在实体之间流动的情况。例如,以居民如何从一个国家迁移到另一个国家为例。这里演示了有多少居民从英格兰迁移到北爱尔兰、苏格兰和威尔士。
  从这个 桑基图 (Sankey)可视化中可以明显看出,从England迁移到Wales的居民多于从Scotland或Northern Ireland迁移的居民。
  什么是桑基图?
  桑基图通常描绘 从一个实体(或节点)到另一个实体(或节点)的数据流。
  数据流向的实体被称为节点,数据流起源的节点是源节点(例如左侧的England),流结束的节点是 目标节点(例如右侧的Wales)。源节点和目标节点通常表示为带有标签的矩形。
  流动本身由直线或曲线路径表示,称为链接。流/链接的宽度与流的量/数量成正比。在上面的例子中,从英格兰到威尔士的流动(即居民迁移)比从英格兰到苏格兰或北爱尔兰的流动(即居民迁移)更广泛(更多),表明迁移到威尔士的居民数量多于其他国家。
  桑基图可用于表示能量、金钱、成本的流动,以及任何具有流动概念的事物。
  米纳尔关于拿破仑入侵俄罗斯的经典图表可能是桑基图表最著名的例子。这种使用桑基图的可视化非常有效地显示了法国军队在前往俄罗斯和返回的途中是如何进步(或减少?)的。
  本文中,我们使用 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

  <class 'pandas.core.frame.DataFrame'>
  RangeIndex: 93 entries, 0 to 92
  Data columns (total 9 columns):
   #   Column         Non-Null Count  Dtype  
  ---  ------         --------------  -----  
   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   Total          93 non-null     int64  
   6   Rank by Total  93 non-null     int64  
   7   Unnamed: 7     0 non-null      float64
   8   Unnamed: 8     1 non-null      float64
  dtypes: float64(2), int64(6), object(1)
  memory usage: 6.7+ KB
  None


  桑基图绘图基础
  使用 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                             2        3       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-Gold          4-Silver        5-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()

  这是一个非常基本的桑基图。但是否注意到图表太宽并且银牌出现在金牌之前?
  接下来介绍如何调整节点的位置和宽度。

TAG: 软件开发 Python

 

评分:0

我来说两句

Open Toolbar