python networkx 繪圖總結

目錄

1、創建方式

2、基本參數

3、DiGraph-有向圖

4、Graph-無向圖

5、有向圖和無向圖互轉

6、一些精美的圖例子


networkx是一個用Python語言開發的圖論與複雜網絡建模工具,內置了常用的圖與複雜網絡分析算法,可以方便的進行復雜網絡數據分析、仿真建模等工作。
利用networkx可以以標準化和非標準化的數據格式存儲網絡、生成多種隨機網絡和經典網絡、分析網絡結構、建立網絡模型、設計新的網絡算法、進行網絡繪製等。
networkx支持創建簡單無向圖、有向圖和多重圖(multigraph);內置許多標準的圖論算法,節點可爲任意數據;支持任意的邊值維度,功能豐富,簡單易用。
networkx以圖(graph)爲基本數據結構。圖既可以由程序生成,也可以來自在線數據源,還可以從文件與數據庫中讀取。

基本流程:
  1. 導入networkx,matplotlib包
  2. 建立網絡
  3. 繪製網絡 nx.draw()
  4. 建立佈局 pos = nx.spring_layout美化作用

1、創建方式

import networkx as nx
import matplotlib.pyplot as plt

# G = nx.random_graphs.barabasi_albert_graph(100, 1)   # 生成一個BA無向圖
# G = nx.MultiGraph()     # 有多重邊無向圖
# G = nx.MultiDiGraph()   # 有多重邊有向圖
# G = nx.Graph()          # 無多重邊無向圖
G = nx.DiGraph()          # 無多重邊有向圖
...
G.clear()  # 清空圖

2、基本參數

2.1 networkx 提供畫圖的函數

  • draw(G,[pos,ax,hold])
  • draw_networkx(G,[pos,with_labels])
  • draw_networkx_nodes(G,pos,[nodelist]) 繪製網絡G的節點圖
  • draw_networkx_edges(G,pos[edgelist]) 繪製網絡G的邊圖
  • draw_networkx_edge_labels(G, pos[, ...]) 繪製網絡G的邊圖,邊有label
  • ---有layout 佈局畫圖函數的分界線---
  • draw_circular(G, **kwargs) Draw the graph G with a circular layout.
  • draw_random(G, **kwargs) Draw the graph G with a random layout.
  • draw_spectral(G, **kwargs) Draw the graph G with a spectral layout.
  • draw_spring(G, **kwargs) Draw the graph G with a spring layout.
  • draw_shell(G, **kwargs) Draw networkx graph with shell layout.
  • draw_graphviz(G[, prog]) Draw networkx graph with graphviz layout.

2.2 networkx 畫圖參數

nx.draw(G,node_size = 30, with_label = False)

上例,繪製節點的尺寸爲30,不帶標籤的網絡圖。

  • node_size: 指定節點的尺寸大小(默認是300,單位未知,就是上圖中那麼大的點)
  • node_color: 指定節點的顏色 (默認是紅色,可以用字符串簡單標識顏色,例如'r'爲紅色,'b'爲綠色等,具體可查看手冊),用“數據字典”賦值的時候必須對字典取值(.values())後再賦值
  • node_shape: 節點的形狀(默認是圓形,用字符串'o'標識,具體可查看手冊)
  • alpha: 透明度 (默認是1.0,不透明,0爲完全透明)
  • width: 邊的寬度 (默認爲1.0)
  • edge_color: 邊的顏色(默認爲黑色)
  • style: 邊的樣式(默認爲實現,可選: solid|dashed|dotted,dashdot)
  • with_labels: 節點是否帶標籤(默認爲True)
  • font_size: 節點標籤字體大小 (默認爲12)
  • font_color: 節點標籤字體顏色(默認爲黑色)

2.3 networkx 畫圖函數裏的一些參數

  • pos(dictionary, optional): 圖像的佈局,可選擇參數;如果是字典元素,則節點是關鍵字,位置是對應的值。如果沒有指明,則會是spring的佈局;也可以使用其他類型的佈局,具體可以查閱networkx.layout
  • arrows :布爾值,默認True; 對於有向圖,如果是True則會畫出箭頭
  • with_labels: 節點是否帶標籤(默認爲True)
  • ax:座標設置,可選擇參數;依照設置好的Matplotlib座標畫圖
  • nodelist:一個列表,默認G.nodes(); 給定節點
  • edgelist:一個列表,默認G.edges();給定邊
  • node_size: 指定節點的尺寸大小(默認是300,單位未知,就是上圖中那麼大的點)
  • node_color: 指定節點的顏色 (默認是紅色,可以用字符串簡單標識顏色,例如’r’爲紅色,'b’爲綠色等,具體可查看手冊),用“數據字典”賦值的時候必須對字典取值(.values())後再賦值
  • node_shape: 節點的形狀(默認是圓形,用字符串’o’標識,具體可查看手冊)
  • alpha: 透明度 (默認是1.0,不透明,0爲完全透明)
  • cmap:Matplotlib的顏色映射,默認None; 用來表示節點對應的強度
  • vmin,vmax:浮點數,默認None;節點顏色映射尺度的最大和最小值
  • linewidths:[None|標量|一列值];圖像邊界的線寬
  • width: 邊的寬度 (默認爲1.0)
  • edge_color: 邊的顏色(默認爲黑色)
  • edge_cmap:Matplotlib的顏色映射,默認None; 用來表示邊對應的強度
  • edge_vmin,edge_vmax:浮點數,默認None;邊的顏色映射尺度的最大和最小值
  • style: 邊的樣式(默認爲實現,可選: solid|dashed|dotted,dashdot)
  • labels:字典元素,默認None;文本形式的節點標籤
  • font_size: 節點標籤字體大小 (默認爲12)
  • font_color: 節點標籤字體顏色(默認爲黑色)
  • node_size:節點大小
  • font_weight:字符串,默認’normal’
  • font_family:字符串,默認’sans-serif’

2.4 佈局指定節點排列形式

pos = nx.spring_layout

建立佈局,對圖進行佈局美化,networkx 提供的佈局方式有:

  • circular_layout:節點在一個圓環上均勻分佈
  • random_layout:節點隨機分佈
  • shell_layout:節點在同心圓上分佈
  • spring_layout: 用Fruchterman-Reingold算法排列節點(這個算法我不瞭解,樣子類似多中心放射狀)
  • spectral_layout:根據圖的拉普拉斯特徵向量排列節

佈局也可用pos參數指定,例如,nx.draw(G, pos = spring_layout(G)) 這樣指定了networkx上以中心放射狀分佈.

3、DiGraph-有向圖

G = nx.DiGraph()        # 無多重邊有向圖
G.add_node(2)  # 添加一個節點
G.add_nodes_from([3, 4, 5, 6, 8, 9, 10, 11, 12])  # 添加多個節點
G.add_cycle([1, 2, 3, 4])  # 添加環
G.add_edge(1, 3)  # 添加一條邊
G.add_edges_from([(3, 5), (3, 6), (6, 7)])  # 添加多條邊
G.remove_node(8)  # 刪除一個節點
G.remove_nodes_from([9, 10, 11, 12])  # 刪除多個節點
print("nodes: ", G.nodes())  # 輸出所有的節點
print("edges: ", G.edges())  # 輸出所有的邊
print("number_of_edges: ", G.number_of_edges())  # 邊的條數,只有一條邊,就是(2,3)
print("degree: ", G.degree)  # 返回節點的度
print("in_degree: ", G.in_degree)  # 返回節點的入度
print("out_degree: ", G.out_degree)  # 返回節點的出度
print("degree_histogram: ", nx.degree_histogram(G))  # 返回所有節點的分佈序列

輸出>>

nodes:  [2, 3, 4, 5, 6, 1, 7]
edges:  [(2, 3), (3, 4), (3, 5), (3, 6), (4, 1), (6, 7), (1, 2), (1, 3)]
number_of_edges:  8
degree:  [(2, 2), (3, 5), (4, 2), (5, 1), (6, 2), (1, 3), (7, 1)]
in_degree:  [(2, 1), (3, 2), (4, 1), (5, 1), (6, 1), (1, 1), (7, 1)]
out_degree:  [(2, 1), (3, 3), (4, 1), (5, 0), (6, 1), (1, 2), (7, 0)]
degree_histogram:  [0, 2, 3, 1, 0, 1]

4、Graph-無向圖

4.1 相關函數:

  • all_neighbors(graph, node):返回圖中節點的所有鄰居
  • non_neighbors(graph, node):返回圖中沒有鄰居的節點
  • common_neighbors(G, u, v):返回圖中兩個節點的公共鄰居
  • non_edges(graph):返回圖中不存在的邊

# 增加節點
G.add_node('a')  # 添加一個節點1
G.add_nodes_from(['b', 'c', 'd', 'e'])  # 加點集合
G.add_cycle(['f', 'g', 'h', 'j'])  # 加環
H = nx.path_graph(10)  # 返回由10個節點的無向圖
G.add_nodes_from(H)  # 創建一個子圖H加入G
G.add_node(H)  # 直接將圖作爲節點

# print("non_edges: ", G.non_edges)  # 返回圖中不存在的邊
print("all_neighbors: ")  # 返回圖中節點的所有鄰居
a = nx.all_neighbors(G, "f")
for i, node in enumerate(a):
    print(i, node)

print("non_neighbors: ")  # 返回圖中沒有鄰居的節點
b = nx.non_neighbors(G, "f")
for i, node in enumerate(b):
    print(i, node)

print("common_neighbors: ")  # 返回圖中兩個節點的公共鄰居
c = nx.common_neighbors(G, "j", "g")
for i, node in enumerate(c):
    print(i, node)

print("non_edges: ")  # 返回圖中不存在的邊
d = nx.non_edges(G)
for i, node in enumerate(d):
    print(i, node)

nx.draw(G, with_labels=True, node_color='red')
plt.show()

 輸出>>

all_neighbors: 
0 g
1 j
non_neighbors: 
0 a   1 b   2 c   3 d   4 e   5 h   6 0   7 1   8 2   9
common_neighbors: 
0 h 
1 f
non_edges: 
0 (0, 'g')
1 (0, 'h')
2 (0, 1)
3 (0, 2)
4 (0, 'e')
...太多了

4.2 屬性

  • 屬性諸如weight,labels,colors,或者任何對象,都可以附加到圖、節點或邊上。
  • 對於每一個圖、節點和邊都可以在關聯的屬性字典中保存一個(多個)鍵-值對。
  • 默認情況下這些是一個空的字典,但是可以增加或者是改變這些屬性。

1、圖的屬性:

G = nx.Graph(day='Monday')  # 可以在創建圖時分配圖的屬性
print(G.graph)

G.graph['day'] = 'Friday'  # 也可以修改已有的屬性
print(G.graph)

G.graph['name'] = 'time'  # 可以隨時添加新的屬性到圖中
print(G.graph)

 輸出>>

{'day': 'Monday'}
{'day': 'Friday'}
{'day': 'Friday', 'name': 'time'}

2、節點的屬性:

G = nx.Graph(day='Monday')
G.add_node(1, index='1th')  # 在添加節點時分配節點屬性
print(G.node(data=True))

G.node[1]['index'] = '0th'  # 通過G.node[][]來添加或修改屬性
print(G.node(data=True))

G.add_nodes_from([2, 3], index='2/3th')  # 從集合中添加節點時分配屬性
print(G.node(data=True))

輸出>>

[(1, {'index': '1th'})]
[(1, {'index': '0th'})]
[(1, {'index': '0th'}), (2, {'index': '2/3th'}), (3, {'index': '2/3th'})]

3、邊的屬性:

G.add_edge(1, 2, weight=10)  # 在添加邊時分配屬性
print(G.edges(data=True))

G.add_edges_from([(1, 3), (4, 5)], len=22)  # 從集合中添加邊時分配屬性
print(G.edges(data='len'))

G.add_edges_from([(3, 4, {'hight': 10}), (1, 4, {'high': 'unknow'})])
print(G.edges(data=True))

G[1][2]['weight'] = 100000  # 通過G[][][]來添加或修改屬性
print(G.edges(data=True))

輸出>>

[(1, 2, {'weight': 10})]
[(1, 2, None), (1, 3, 22), (4, 5, 22)]
[(1, 2, {'weight': 10}), (1, 3, {'len': 22}), (1, 4, {'high': 'unknow'}), (3, 4, {'hight': 10}), (4, 5, {'len': 22})]
[(1, 2, {'weight': 100000}), (1, 3, {'len': 22}), (1, 4, {'high': 'unknow'}), (3, 4, {'hight': 10}), (4, 5, {'len': 22})]

5、有向圖和無向圖互轉

有向圖和多重圖的基本操作與無向圖一致。
無向圖與有向圖之間可以相互轉換。

G = nx.DiGraph()

H = G.to_undirected()  # 有向圖轉化成無向圖-方法1
H = nx.Graph(G)        # 有向圖轉化成無向圖-方法2

F = H.to_directed()  # 無向圖轉化成有向圖-方法1
F = nx.DiGraph(H)    # 無向圖轉化成有向圖-方法2

6、一些精美的圖例子

使用pydot時會遇見如下的錯誤:

FileNotFoundError: [WinError 2] "twopi" not found in path.

解決參考:

1、 環形樹狀圖

# 環形樹狀圖
import os
import pydot
from networkx.drawing.nx_pydot import graphviz_layout

def set_prog(prog="dot"):
  
    path = r'C:\Program Files (x86)\Graphviz 2.28\bin'  # graphviz的bin目錄
    prog = os.path.join(path, prog) + '.exe'
    return prog


G = nx.balanced_tree(3, 5)
pos = graphviz_layout(G, prog=set_prog("twopi"))
plt.figure(figsize=(8, 8))
nx.draw(G, pos, node_size=20, alpha=0.5, node_color="blue", with_labels=False)
plt.axis('equal')
plt.show()

 2、權重圖

G = nx.Graph()

G.add_edge('a', 'b', weight=0.6)
G.add_edge('a', 'c', weight=0.2)
G.add_edge('c', 'd', weight=0.1)
G.add_edge('c', 'e', weight=0.7)
G.add_edge('c', 'f', weight=0.9)
G.add_edge('a', 'd', weight=0.3)

elarge = [(u, v) for (u, v, d) in G.edges(data=True) if d['weight'] > 0.5]
esmall = [(u, v) for (u, v, d) in G.edges(data=True) if d['weight'] <= 0.5]

pos = nx.spring_layout(G)  # positions for all nodes

# nodes
nx.draw_networkx_nodes(G, pos, node_size=700)

# edges
nx.draw_networkx_edges(G, pos, edgelist=elarge, width=6)
nx.draw_networkx_edges(G, pos, edgelist=esmall, width=6, alpha=0.5, edge_color='b', style='dashed')

# labels-標籤
# nx.draw_networkx_labels(G, pos, font_size=20, font_family='sans-serif')

plt.axis('off')
plt.show()

3、Giant Component 

import pydot
from networkx.drawing.nx_pydot import graphviz_layout


def set_prog(prog="dot"):
    path = r'C:\Program Files (x86)\Graphviz 2.28\bin'  # graphviz的bin目錄
    prog = os.path.join(path, prog) + '.exe'
    return prog


pvals = [0.003, 0.006, 0.008, 0.015]  # the range of p values should be close to the threshold

plt.subplots_adjust(left=0, right=1, bottom=0, top=0.95, wspace=0.01, hspace=0.01)
for i, p in enumerate(pvals):
    G = nx.binomial_graph(150, p)  # 150 nodes
    pos = graphviz_layout(G, prog=set_prog("neato"))
    plt.subplot(2, 2, i + 1)
    plt.title("p = %6.3f" % (p,))
    nx.draw(G, pos, with_labels=False, node_size=10)
    # 找出最大連通數的子圖
    Gcc = sorted(nx.connected_component_subgraphs(G), key=len, reverse=True)
    G0 = Gcc[0]
    nx.draw_networkx_edges(G0, pos, with_labels=False, edge_color='r', width=6.0)
    # 畫出其他連通數子圖
    [nx.draw_networkx_edges(Gi, pos, with_labels=False, edge_color='r', alpha=0.3, width=5.0) for Gi in Gcc[1:] if
     len(Gi) > 1]
plt.show()

4、Random Geometric Graph 隨機幾何圖


G = nx.random_geometric_graph(200, 0.125)
pos = nx.get_node_attributes(G, 'pos')  # position is stored as node attribute data for random_geometric_graph

# find node near center (0.5,0.5)
dmin = 1
ncenter = 0
for n in pos:
    x, y = pos[n]
    d = (x - 0.5) ** 2 + (y - 0.5) ** 2
    if d < dmin:
        ncenter = n
        dmin = d

# color by path length from node near center
p = dict(nx.single_source_shortest_path_length(G, ncenter))

plt.figure(figsize=(8, 8))
nx.draw_networkx_edges(G, pos, nodelist=[ncenter], alpha=0.4)
nx.draw_networkx_nodes(G, pos, nodelist=list(p.keys()), node_size=80,  node_color=list(p.values()), cmap=plt.cm.Reds_r)

plt.xlim(-0.05, 1.05)
plt.ylim(-0.05, 1.05)
plt.show()

5、節點顏色漸變

G = nx.cycle_graph(24)
pos = nx.spring_layout(G, iterations=200)
nx.draw(G, pos, node_color=range(24), node_size=800, cmap=plt.cm.Blues)
plt.show()

 6、邊顏色漸變

G = nx.star_graph(20)
pos = nx.spring_layout(G)  # 佈局爲中心放射狀
colors = range(20)
nx.draw(G, pos, node_color='#A0CBE2', edge_color=colors, width=2, edge_cmap=plt.cm.Blues, with_labels=False)
plt.show()

7、Atlas

import os
import pydot
import random
from networkx.generators.atlas import graph_atlas_g
from networkx.drawing.nx_pydot import graphviz_layout
from networkx.algorithms.isomorphism.isomorph import graph_could_be_isomorphic as isomorphic


def set_prog(prog="dot"):
    path = r'C:\Program Files (x86)\Graphviz 2.28\bin'  # graphviz的bin目錄
    prog = os.path.join(path, prog) + '.exe'
    return prog


def atlas6():
    """ Return the atlas of all connected graphs of 6 nodes or less.
        Attempt to check for isomorphisms and remove.
    """

    Atlas = graph_atlas_g()[0:208]  # 208
    # remove isolated nodes, only connected graphs are left
    U = nx.Graph()  # graph for union of all graphs in atlas
    for G in Atlas:
        for n in [n for n in G if G.degree(n) == 0]:
            G.remove_node(n)
        U = nx.disjoint_union(U, G)

    # iterator of graphs of all connected components
    C = (U.subgraph(c) for c in nx.connected_components(U))

    UU = nx.Graph()
    # do quick isomorphic-like check, not a true isomorphism checker
    nlist = []  # list of nonisomorphic graphs
    for G in C:
        # check against all nonisomorphic graphs so far
        if not iso(G, nlist):
            nlist.append(G)
            UU = nx.disjoint_union(UU, G)  # union the nonisomorphic graphs
    return UU


def iso(G1, glist):
    """Quick and dirty nonisomorphism checker used to check isomorphisms."""
    if any(isomorphic(G1, G2) for G2 in glist):
        return True
    return False


G = atlas6()
print("graph has %d nodes with %d edges" % (nx.number_of_nodes(G), nx.number_of_edges(G)))
print(nx.number_connected_components(G), "connected components")
plt.figure(1, figsize=(8, 8))
pos = graphviz_layout(G, prog=set_prog("neato"))
# color nodes the same in each connected subgraph
C = (G.subgraph(c) for c in nx.connected_components(G))
for g in C:
    c = [random.random()] * nx.number_of_nodes(g)  # random color...
    nx.draw(g, pos, node_size=40, node_color=c, vmin=0.0, vmax=1.0, with_labels=False)
plt.show()

8、Club

import networkx.algorithms.bipartite as bipartite

G = nx.davis_southern_women_graph()
women = G.graph['top']
clubs = G.graph['bottom']

print("Biadjacency matrix")
print(bipartite.biadjacency_matrix(G, women, clubs))

# project bipartite graph onto women nodes
W = bipartite.projected_graph(G, women)
print('')
print("#Friends, Member")
for w in women:
    print('%d %s' % (W.degree(w), w))

# project bipartite graph onto women nodes keeping number of co-occurence
# the degree computed is weighted and counts the total number of shared contacts
W = bipartite.weighted_projected_graph(G, women)
print('')
print("#Friend meetings, Member")
for w in women:
    print('%d %s' % (W.degree(w, weight='weight'), w))

nx.draw(G, node_color="red")
plt.show()

 


參考:

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章