用NetworkX生成並繪製(帶權)無向圖

orion發表於2022-05-11

NetworkX是一個非常強大的網路科學工具,它封裝了圖的資料結構和許多經典圖演算法,也內建了許多視覺化函式可供呼叫。

1. 隨機圖生成

最經典的隨機圖當屬我們在上一篇部落格《Erdos-Renyi隨機圖的生成方式及其特性》中講到的Erdős-Rény隨機圖了,我們這裡選用其中的\(?_{np}\)形式,呼叫以下API:

G = nx.erdos_renyi_graph(10, 0.3, seed=1)

這裡表示生成10個頂點的圖,且圖的每條邊都以0.3的概率產生。

當然,此時生成的圖不具有權重,我們想在此基礎上均勻隨機初始化[0, 0.4]之間的權重,可以這樣寫:

G = nx.Graph()
for u, v in nx.erdos_renyi_graph(10, 0.3, seed=1).edges():
    G.add_edge(u, v, weight=random.uniform(0, 0.4))

2. 2D佈局視覺化

隨機圖生成好之後,我們就要對其進行視覺化了。首先我們需要計算每個節點在圖中擺放的位置,經典的Fruchterman-Reingold force-directed 演算法可以完成這個操作,對應NetworkX中的spring_layout函式:

pos = nx.spring_layout(G, iterations=20) #我們設演算法迭代次數為20次

然後就可以分別繪製圖的邊、節點和節點標籤了:

nx.draw_networkx_edges(G, pos, edge_color="orange")
nx.draw_networkx_nodes(G, pos, node_color="black")
nx.draw_networkx_labels(G, pos, font_color="white")
plt.show()

繪圖結果如下:

NLP多工學習

當然,這樣圖的權值是無法體現於圖上的,如果我們需要圖的權值體現於圖上,可以使圖中邊的寬度按照權值大小來設定:

nx.draw_networkx_edges(G,pos, width=[float(d['weight']*10) for (u,v,d) in G.edges(data=True)], edge_color="orange")
nx.draw_networkx_nodes(G,pos, node_color="black")
nx.draw_networkx_labels(G, pos, font_color="white")
plt.show()

此時的繪圖結果如下:

NLP多工學習

3. 3D佈局視覺化

如果你覺得2D佈局過於扁平,還不夠直觀地體現節點之間的拓撲關係,那你可以採用如下的程式碼對圖進行三維視覺化:

# 3d spring layout
pos = nx.spring_layout(G, dim=3, seed=779)
# Extract node and edge positions from the layout
node_xyz = np.array([pos[v] for v in sorted(G)])
edge_xyz = np.array([(pos[u], pos[v]) for u, v in G.edges()])

# Create the 3D figure
fig = plt.figure()
ax = fig.add_subplot(111, projection="3d")

# Plot the nodes - alpha is scaled by "depth" automatically
ax.scatter(*node_xyz.T, s=100, ec="w")

# Plot the edges
for vizedge in edge_xyz:
    ax.plot(*vizedge.T, color="tab:gray")


def _format_axes(ax):
    """Visualization options for the 3D axes."""
    # Turn gridlines off
    ax.grid(False)
    # Suppress tick labels
    for dim in (ax.xaxis, ax.yaxis, ax.zaxis):
        dim.set_ticks([])
    # Set axes labels
    ax.set_xlabel("x")
    ax.set_ylabel("y")
    ax.set_zlabel("z")


_format_axes(ax)
fig.tight_layout()
plt.show()

此時的繪圖結果如下:

NLP多工學習

參考

相關文章