Rumah  >  Artikel  >  pembangunan bahagian belakang  >  Python melukis gambar rajah Sankey yang menakjubkan, adakah anda telah mempelajarinya?

Python melukis gambar rajah Sankey yang menakjubkan, adakah anda telah mempelajarinya?

王林
王林ke hadapan
2023-04-12 14:28:081868semak imbas

Pengenalan kepada Rajah Sankey

Banyak kali, kita memerlukan situasi di mana kita perlu memvisualisasikan cara data mengalir antara entiti. Sebagai contoh, ambil cara penduduk berpindah dari satu negara ke negara lain. Berikut ialah demonstrasi bilangan penduduk yang berpindah dari England ke Ireland Utara, Scotland dan Wales.

Python melukis gambar rajah Sankey yang menakjubkan, adakah anda telah mempelajarinya?

Terbukti daripada visualisasi Sankey ini bahawa lebih ramai penduduk berpindah dari England ke Wales berbanding dari Scotland atau Ireland Utara.

Apakah gambar rajah Sankey?

Gambar rajah Sankey biasanya menggambarkan aliran data dari satu entiti (atau nod) ke entiti yang lain.

Entiti yang mengalirkan data dipanggil nod tempat aliran data berasal ialah nod sumber (seperti England di sebelah kiri), dan nod tempat aliran berakhir ialah nod sasaran (seperti itu. sebagai Wales di sebelah kanan). Nod sumber dan sasaran biasanya diwakili sebagai segi empat tepat berlabel.

Aliran itu sendiri diwakili oleh laluan lurus atau melengkung, dipanggil pautan. Lebar strim/pautan adalah berkadar terus dengan volum/bilangan strim. Dalam contoh di atas, pergerakan dari England ke Wales (iaitu penghijrahan penduduk) adalah lebih meluas (iaitu penghijrahan penduduk) daripada pergerakan dari England ke Scotland atau Ireland Utara (iaitu penghijrahan penduduk), menunjukkan bahawa lebih ramai penduduk berpindah ke Wales berbanding ke negara lain .

Rajah Sankey boleh digunakan untuk mewakili aliran tenaga, wang, kos dan apa-apa sahaja dengan konsep aliran.

Rajah klasik Minard tentang pencerobohan Napoleon ke atas Rusia mungkin merupakan contoh gambar rajah Sankey yang paling terkenal. Visualisasi menggunakan rajah Sankey ini menunjukkan dengan sangat berkesan bagaimana tentera Perancis maju (atau menurun?) dalam perjalanan ke Rusia dan kembali.

Python melukis gambar rajah Sankey yang menakjubkan, adakah anda telah mempelajarinya?

Dalam artikel ini, kami menggunakan plot python untuk melukis gambar rajah Sankey.

Bagaimana untuk melukis gambar rajah Sankey?

Artikel ini menggunakan set data Sukan Olimpik 2021 untuk melukis gambar rajah Sankey. Set data mengandungi maklumat terperinci tentang jumlah pingat - negara, jumlah pingat dan jumlah individu untuk pingat emas, perak dan gangsa. Kami merancang carta Sankey untuk mengetahui berapa banyak pingat emas, perak dan gangsa yang dimenangi oleh sesebuah negara.

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 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 melukis gambar rajah Sankey yang menakjubkan, adakah anda telah mempelajarinya?

Asas lukisan rajah Sankey

Gunakan plotly's go.Sankey.Kaedah ini mengambil 2 parameter - nod dan pautan (nod dan pautan ).

Nota: Semua nod - sumber dan sasaran harus mempunyai pengecam unik.

Dalam kes set data pingat Olimpik dalam artikel ini:

Sumber ialah negara. Pertimbangkan 3 negara pertama (Amerika Syarikat, China dan Jepun) sebagai nod sumber. Labelkan nod sumber ini dengan pengecam, label dan warna (unik) berikut:

  • 0: Amerika Syarikat: hijau
  • 1: China: biru
  • 2 : Jepun: Jingga

Sasaran ialah emas, perak atau gangsa. Labelkan nod sasaran ini dengan pengecam, label dan warna (unik) berikut:

  • 3: Emas: Emas
  • 4: Perak: Perak
  • 5 : Gangsa: Coklat

Pautan (antara nod sumber dan nod sasaran) ialah bilangan pingat bagi setiap jenis. Dalam setiap sumber terdapat 3 pautan, setiap satu berakhir dengan sasaran - Emas, Perak dan Gangsa. Jadi ada 9 pautan kesemuanya. Lebar setiap pautan hendaklah bilangan pingat emas, perak dan gangsa. Labelkan pautan ini kepada sasaran, nilai dan warna dengan sumber berikut:

  • 0 (AS) hingga 3,4,5 : 39, 41, 33
  • 1 (China ) hingga 3 ,4,5 : 38, 32, 18
  • 2 (Jepun) hingga 3,4,5 : 27, 14, 17

Anda perlu membuat instantiate 2 ular sawa dict objek kepada Mewakili

  • nod (sumber dan sasaran): label dan warna sebagai senarai berasingan dan
  • pautan: nod sumber, nod sasaran, nilai (lebar) dan warna pautan sebagai pisahkan Senarai

dan hantarkannya ke plotly’s go.Sankey.

Setiap indeks senarai (label, sumber, sasaran, nilai dan warna) sepadan dengan nod atau pautan.

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 melukis gambar rajah Sankey yang menakjubkan, adakah anda telah mempelajarinya?

Ini ialah rajah Sankey yang sangat asas. Tetapi adakah anda perasan bahawa carta terlalu lebar dan pingat perak muncul sebelum pingat emas?

Laraskan kedudukan nod dan lebar carta

Tambahkan kedudukan x dan y pada nod untuk menyatakan kedudukan nod secara eksplisit. Nilai hendaklah antara 0 dan 1.

Jadi kami mendapat gambar rajah Sankey padat:
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 melukis gambar rajah Sankey yang menakjubkan, adakah anda telah mempelajarinya?Mari kita lihat bagaimana pelbagai parameter yang diluluskan dalam kod dipetakan ke rajah Nod dan pautan.

Python melukis gambar rajah Sankey yang menakjubkan, adakah anda telah mempelajarinya?

代码如何映射到桑基图

添加有意义的悬停标签

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

Python melukis gambar rajah Sankey yang menakjubkan, adakah anda telah mempelajarinya?

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

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

例如:

  • 节点美国共获得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 melukis gambar rajah Sankey yang menakjubkan, adakah anda telah mempelajarinya?

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

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

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

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

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 melukis gambar rajah Sankey yang menakjubkan, adakah anda telah mempelajarinya?

Atas ialah kandungan terperinci Python melukis gambar rajah Sankey yang menakjubkan, adakah anda telah mempelajarinya?. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Kenyataan:
Artikel ini dikembalikan pada:51cto.com. Jika ada pelanggaran, sila hubungi admin@php.cn Padam