Rumah > Artikel > pembangunan bahagian belakang > Python melukis gambar rajah Sankey yang menakjubkan, adakah anda telah mempelajarinya?
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.
Terbukti daripada visualisasi Sankey ini bahawa lebih ramai penduduk berpindah dari England ke Wales berbanding dari Scotland atau Ireland Utara.
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.
Dalam artikel ini, kami menggunakan plot python 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
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:
Sasaran ialah emas, perak atau gangsa. Labelkan nod sasaran ini dengan pengecam, label dan warna (unik) berikut:
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:
Anda perlu membuat instantiate 2 ular sawa dict objek kepada Mewakili
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()
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
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()
Mari kita lihat bagaimana pelbagai parameter yang diluluskan dalam kod dipetakan ke rajah Nod dan pautan.
代码如何映射到桑基图
我们都知道plotly绘图是交互的,我们可以将鼠标悬停在节点和链接上以获取更多信息。
带有默认悬停标签的桑基图
当将鼠标悬停在图上,将会显示详细信息。悬停标签中显示的信息是默认文本:节点、节点名称、传入流数、传出流数和总值。
例如:
如果我们觉得这些标签太冗长了,我们可以对此进程改进。使用hovertemplate参数改进悬停标签的格式
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()
带有改进的悬停标签的桑基图
对多个节点和级别进行泛化相对于链接,节点被称为源和目标。作为一个链接目标的节点可以是另一个链接的源。
该代码可以推广到处理数据集中的所有国家。
还可以将图表扩展到另一个层次,以可视化各国的奖牌总数。
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")
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!