Heim >Backend-Entwicklung >Python-Tutorial >Python zeichnet atemberaubende Sankey-Diagramme. Haben Sie es gelernt?

Python zeichnet atemberaubende Sankey-Diagramme. Haben Sie es gelernt?

王林
王林nach vorne
2023-04-12 14:28:082040Durchsuche

Einführung in Sankey-Diagramme

Oft brauchen wir eine Situation, in der wir visualisieren müssen, wie Daten zwischen Entitäten fließen. Nehmen wir zum Beispiel, wie Einwohner von einem Land in ein anderes ziehen. Hier ist eine Demonstration, wie viele Einwohner von England nach Nordirland, Schottland und Wales gezogen sind.

Python zeichnet atemberaubende Sankey-Diagramme. Haben Sie es gelernt?

Aus dieser Sankey-Visualisierung geht klar hervor, dass mehr Einwohner von England nach Wales gezogen sind als aus Schottland oder Nordirland.

Was ist ein Sankey-Diagramm?

Sankey-Diagramme stellen normalerweise den Datenfluss von einer Entität (oder einem Knoten) zu einer anderen Entität (oder einem anderen Knoten) dar.

Die Entitäten, zu denen Daten fließen, werden als Knoten bezeichnet. Der Knoten, von dem der Datenfluss ausgeht, ist der Quellknoten (z. B. England auf der linken Seite), und der Knoten, an dem der Datenfluss endet, ist der Zielknoten (z. B. Wales auf der rechten Seite). ). Quell- und Zielknoten werden normalerweise als beschriftete Rechtecke dargestellt.

Der Fluss selbst wird durch gerade oder gekrümmte Pfade, sogenannte Links, dargestellt. Die Breite eines Streams/Links ist direkt proportional zur Lautstärke/Anzahl der Streams. Im obigen Beispiel ist die Bewegung von England nach Wales (d. h. die Migration von Einwohnern) umfangreicher (d. h. die Migration von Einwohnern) als die Bewegung von England nach Schottland oder Nordirland (d. h. die Migration von Einwohnern), was darauf hindeutet, dass mehr Einwohner Ziehen Sie lieber nach Wales als in andere Länder.

Sankey-Diagramme können verwendet werden, um den Fluss von Energie, Geld, Kosten und allem anderen mit einem Flusskonzept darzustellen.

Minards klassische Karte von Napoleons Invasion in Russland ist wahrscheinlich das berühmteste Beispiel einer Sankey-Karte. Diese Visualisierung mithilfe eines Sankey-Diagramms zeigt sehr effektiv, wie die französische Armee auf ihrem Weg nach Russland und zurück vorankam (oder abnahm?).

Python zeichnet atemberaubende Sankey-Diagramme. Haben Sie es gelernt?

In diesem Artikel verwenden wir Pythons Plotly, um ein Sankey-Diagramm zu zeichnen.

Wie zeichnet man ein Sankey-Diagramm?

In diesem Artikel wird der Datensatz der Olympischen Spiele 2021 verwendet, um ein Sankey-Diagramm zu zeichnen. Der Datensatz enthält detaillierte Informationen über die Gesamtzahl der Medaillen – Land, Gesamtzahl der Medaillen und individuelle Gesamtzahlen für Gold-, Silber- und Bronzemedaillen. Wir erstellen ein Sankey-Diagramm, um herauszufinden, wie viele Gold-, Silber- und Bronzemedaillen ein Land gewonnen hat.

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 zeichnet atemberaubende Sankey-Diagramme. Haben Sie es gelernt?

Grundlagen des Sankey-Diagrammzeichnens

Verwenden Sie plotlys go.Sankey. Diese Methode benötigt 2 Parameter – Knoten und Links (Knoten und Links).

Hinweis: Alle Knoten – Quelle und Ziel – sollten eindeutige Kennungen haben.

Im Fall des olympischen Medaillendatensatzes dieses Artikels:

Quelle ist das Land. Betrachten Sie die ersten drei Länder (USA, China und Japan) als Quellknoten. Beschriften Sie diese Quellknoten mit den folgenden (eindeutigen) Kennungen, Bezeichnungen und Farben:

  • 0: Vereinigte Staaten: Grün
  • 1: China: Blau
  • 2: Japan: Orange

Ziel ist Gold, Silber oder Bronzemedaille. Beschriften Sie diese Zielknoten mit den folgenden (eindeutigen) Bezeichnern, Beschriftungen und Farben:

  • 3: Gold: Gold
  • 4: Silber: Silber
  • 5: Bronze: Braun

Link (Quellknoten und Zielknoten) ist die Anzahl der Medaillen jeder Art. In jeder Quelle gibt es 3 Links, die jeweils mit einem Ziel enden – Gold, Silber und Bronze. Insgesamt gibt es also 9 Links. Die Breite jedes Glieds sollte der Anzahl der Gold-, Silber- und Bronzemedaillen entsprechen. Beschriften Sie diese Links zu Zielen, Werten und Farben mit den folgenden Quellen:

  • 0 (USA) bis 3,4,5 : 39, 41, 33
  • 1 (China) bis 3,4,5 : 38, 32, 18
  • 2 (Japan) bis 3,4,5 : 27, 14, 17

Erfordert die Instanziierung von 2 Python-Diktobjekten zur Darstellung von

  • Knoten (Quelle und Ziel): Beschriftungen und Farben als separate Listen und
  • Links: Quellknoten, Zielknoten, Wert (Breite) und Farbe des Links als separate Listen

und an plotly’s go.Sankey übergeben.

Jeder Index der Liste (Beschriftung, Quelle, Ziel, Wert und Farbe) entspricht einem Knoten oder Link.

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 zeichnet atemberaubende Sankey-Diagramme. Haben Sie es gelernt?

Dies ist ein sehr einfaches Sankey-Diagramm. Aber ist Ihnen schon einmal aufgefallen, dass das Diagramm zu breit ist und die Silbermedaillen vor den Goldmedaillen erscheinen?

So passen Sie die Position und Breite der Knoten an.

Knotenpositionen und Diagrammbreite anpassen

X- und Y-Positionen für Knoten hinzufügen, um die Position des Knotens explizit anzugeben. Der Wert sollte zwischen 0 und 1 liegen.

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()

Also haben wir ein kompaktes Sankey-Diagramm erhalten:

Python zeichnet atemberaubende Sankey-Diagramme. Haben Sie es gelernt?

Werfen wir einen Blick darauf, wie die verschiedenen im Code übergebenen Parameter den Knoten und Links im Diagramm zugeordnet werden.

Python zeichnet atemberaubende Sankey-Diagramme. Haben Sie es gelernt?

代码如何映射到桑基图

添加有意义的悬停标签

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

Python zeichnet atemberaubende Sankey-Diagramme. Haben Sie es gelernt?

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

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

例如:

  • 节点美国共获得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 zeichnet atemberaubende Sankey-Diagramme. Haben Sie es gelernt?

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

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

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

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

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 zeichnet atemberaubende Sankey-Diagramme. Haben Sie es gelernt?

Das obige ist der detaillierte Inhalt vonPython zeichnet atemberaubende Sankey-Diagramme. Haben Sie es gelernt?. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Dieser Artikel ist reproduziert unter:51cto.com. Bei Verstößen wenden Sie sich bitte an admin@php.cn löschen