networkx整理

一、基礎知識

1.一、介紹

networkx在2002年5月產生,是一個用Python語言開發的圖論與複雜網絡建模工具,內置了經常使用的圖與複雜網絡分析算法,能夠方便的進行復雜網絡數據分析、仿真建模等工做。php

networkx支持建立簡單無向圖、有向圖和多重圖;內置許多標準的圖論算法,節點可爲任意數據;支持任意的邊值維度,功能豐富,簡單易用。html

1.二、做用

利用networkx能夠以標準化和非標準化的數據格式存儲網絡、生成多種隨機網絡和經典網絡、分析網絡結構、創建網絡模型、設計新的網絡算法、進行網絡繪製等。node

1.三、Graph

1.3.一、Graph的定義

Graph是用點和線來刻畫離散事物集合中的每對事物間以某種方式相聯繫的數學模型。python

網絡做爲圖的一個重要領域,包含的概念與定義更多,若有向圖網絡(Directed Graphs and Networks)、無向圖網絡(Undirected)等概念。算法

Graph在現實世界中隨處可見,如交通運輸圖、旅遊圖、流程圖等。此處咱們只考慮由點和線所組成的圖。spring

利用圖能夠描述現實生活中的許多事物,如用點能夠表示交叉口,點之間的連線表示路徑,這樣就能夠垂手可得的描繪出一個交通運輸網絡。shell

1.3.二、Graph的結構

根據Graph的定義,一個Graph包含一個節點集合和一個邊集。網絡

在NetworkX中,一個節點能夠是任意hash對象(除了None對象),一條邊也能夠關聯任意的對象,像一個文本字符串,一幅圖像,一個XML對象,甚至是另外一個圖或任意定製的節點對象。函數

注意:Python中的None對象是不能夠做爲節點的類型的。工具

節點與邊可以存儲任意類型字典的屬性和任意其餘豐富類型的數據。

1.3.三、Graph分類

  • Graph:指無向圖(undirected Graph),即忽略了兩節點間邊的方向。
  • DiGraph:指有向圖(directed Graph),即考慮了邊的有向性。
  • MultiGraph:指多重無向圖,即兩個結點之間的邊數多於一條,又容許頂點經過同一條邊和本身關聯。
  • MultiDiGraph:多重圖的有向版本。
G = nx.Graph() # 建立無向圖
 G = nx.DiGraph() # 建立有向圖
 G = nx.MultiGraph() # 建立多重無向圖
 G = nx.MultiDigraph() # 建立多重有向圖
 G.clear() #清空圖

二、基本操做

 2.一、無向圖

  • 節點 

————若是添加的節點和邊是已經存在的,是不會報錯的,NetworkX會自動忽略掉已經存在的邊和節點的添加。

#添加節點
import networkx as nx import matplotlib.pyplot as plt G = nx.Graph() #創建一個空的無向圖G 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個節點挨個鏈接的無向圖,因此有9條邊 G.add_nodes_from(H) #建立一個子圖H加入G G.add_node(H) #直接將圖做爲節點 nx.draw(G, with_labels=True) plt.show()

#訪問節點

print('圖中全部的節點', G.nodes()) print('圖中節點的個數', G.number_of_nodes())

 

#刪除節點
 G.remove_node(1)    #刪除指定節點
G.remove_nodes_from(['b','c','d','e'])    #刪除集合中的節點
 nx.draw(G, with_labels=True) plt.show()

#添加邊
 F = nx.Graph() # 建立無向圖
F.add_edge(11,12)   #一次添加一條邊

#等價於
e=(13,14)        #e是一個元組
F.add_edge(*e) #這是python中解包裹的過程
 F.add_edges_from([(1,2),(1,3)])     #經過添加list來添加多條邊

#經過添加任何ebunch來添加邊
F.add_edges_from(H.edges()) #不能寫做F.add_edges_from(H)
 nx.draw(F, with_labels=True) plt.show()

#訪問邊

print('圖中全部的邊', F.edges()) print('圖中邊的個數', F.number_of_edges()) 

 

#快速遍歷每一條邊,可使用鄰接迭代器實現,對於無向圖,每一條邊至關於兩條有向邊
FG = nx.Graph() FG.add_weighted_edges_from([(1,2,0.125), (1,3,0.75), (2,4,1.2), (3,4,0.275)]) for n, nbrs in FG.adjacency(): for nbr, eattr in nbrs.items(): data = eattr['weight'] print('(%d, %d, %0.3f)' % (n,nbr,data)) print('***********************************') #篩選weight小於0.5的邊:
FG = nx.Graph() FG.add_weighted_edges_from([(1,2,0.125), (1,3,0.75), (2,4,1.2), (3,4,0.275)]) for n, nbrs in FG.adjacency(): for nbr, eattr in nbrs.items(): data = eattr['weight'] if data < 0.5: print('(%d, %d, %0.3f)' % (n,nbr,data)) print('***********************************') #一種方便的訪問全部邊的方法:
for u,v,d in FG.edges(data = 'weight'): print((u,v,d))

 

#刪除邊
 F.remove_edge(1,2) F.remove_edges_from([(11,12), (13,14)]) nx.draw(F, with_labels=True) plt.show()

  • 屬性

屬性諸如weight,labels,colors,或者任何對象,你均可以附加到圖、節點或邊上。

對於每個圖、節點和邊均可以在關聯的屬性字典中保存一個(多個)鍵-值對。

默認狀況下這些是一個空的字典,可是咱們能夠增長或者是改變這些屬性。

#圖的屬性

import networkx as nx import matplotlib.pyplot as plt G = nx.Graph(day='Monday')    #能夠在建立圖時分配圖的屬性
print(G.graph) G.graph['day'] = 'Friday'     #也能夠修改已有的屬性
print(G.graph) G.graph['name'] = 'time'      #能夠隨時添加新的屬性到圖中
print(G.graph)

#節點的屬性
 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.nodes(data=True)) print(G.node(data=True))

#邊的屬性
 G = nx.Graph(day='manday') 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))

注意

注意何時使用‘=’,何時使用‘:’;何時有引號何時沒有引號。

特殊屬性weight應該是一個數值型的,而且在算法須要使用weight時保存該數值。

 2.二、其餘圖

有向圖和多重圖的基本操做與無向圖一致。

無向圖與有向圖之間能夠相互轉換,轉化方法以下:

#有向圖轉化成無向圖
 H=DG.to_undirected() #或者
H=nx.Graph(DG) #無向圖轉化成有向圖
 F = H.to_directed() #或者
F = nx.DiGraph(H)

三、Functions

degree(G[, nbunch, weight]):返回單個節點或nbunch節點的度數視圖。 

degree_histogram(G):返回每一個度值的頻率列表。

density(G):返回圖的密度。

info(G[, n]):打印圖G或節點n的簡短信息摘要。

create_empty_copy(G[, with_data]):返回圖G刪除全部的邊的拷貝。

is_directed(G):若是圖是有向的,返回true。

add_star(G_to_add_to, nodes_for_star, **attr):在圖形G_to_add_to上添加一個星形。

add_path(G_to_add_to, nodes_for_path, **attr):在圖G_to_add_to中添加一條路徑。

add_cycle(G_to_add_to, nodes_for_cycle, **attr):向圖形G_to_add_to添加一個循環。

  • 節點

nodes(G):在圖節點上返回一個迭代器。

number_of_nodes(G):返回圖中節點的數量。

all_neighbors(graph, node):返回圖中節點的全部鄰居。

non_neighbors(graph, node):返回圖中沒有鄰居的節點。

common_neighbors(G, u, v):返回圖中兩個節點的公共鄰居。

edges(G[, nbunch]):返回與nbunch中的節點相關的邊的視圖。

number_of_edges(G):返回圖中邊的數目。

non_edges(graph):返回圖中不存在的邊。

  •  實例:在networkx中列出特定的節點或邊緣

import networkx as nx import matplotlib.pyplot as plt G = nx.DiGraph() G.add_edges_from([('n', 'n1'), ('n', 'n2'), ('n', 'n3')]) G.add_edges_from([('n4', 'n41'), ('n1', 'n11'), ('n1', 'n12'), ('n1', 'n13')]) G.add_edges_from([('n2', 'n21'), ('n2', 'n22')]) G.add_edges_from([('n13', 'n131'), ('n22', 'n221')]) G.add_edges_from([('n131', 'n221'), ('n221', 'n131')]) G.add_node('n5') nx.draw(G, with_labels=True) plt.show()

一、使用out_degree函數查找全部帶有子項的節點:

>>> [k for k,v in G.out_degree().iteritems() if v > 0] ['n13', 'n', 'n131', 'n1', 'n22', 'n2', 'n221', 'n4']

二、全部沒有孩子的節點:

>>> [k for k,v in G.out_degree().iteritems() if v == 0] ['n12', 'n11', 'n3', 'n41', 'n21', 'n5']

三、全部孤兒節點,即度數爲0的節點:

>>> [k for k,v in G.degree().iteritems() if v == 0] ['n5'

四、超過2個孩子的節點:

>>> [k for k,v in G.out_degree().iteritems() if v > 2] ['n', 'n1']

四、經典圖論算法 

  • 最短路徑  

函數調用: 

dijkstra_path(G, source, target, weight='weight')             ————求最短路徑

dijkstra_path_length(G, source, target, weight='weight')      ————求最短距離

示例

import networkx as nx import pylab import numpy as np #自定義網絡
row=np.array([0,0,0,1,2,3,6]) col=np.array([1,2,3,4,5,6,7]) value=np.array([1,2,1,8,1,3,5]) print('生成一個空的有向圖') G=nx.DiGraph() print('爲這個網絡添加節點...') for i in range(0,np.size(col)+1): G.add_node(i) print('在網絡中添加帶權中的邊...') for i in range(np.size(row)): G.add_weighted_edges_from([(row[i],col[i],value[i])]) print('給網路設置佈局...') pos=nx.shell_layout(G) print('畫出網絡圖像:') nx.draw(G,pos,with_labels=True, node_color='white', edge_color='red', node_size=400, alpha=0.5 ) pylab.title('Self_Define Net',fontsize=15) pylab.show() ''' Shortest Path with dijkstra_path '''
print('dijkstra方法尋找最短路徑:') path=nx.dijkstra_path(G, source=0, target=7) print('節點0到7的路徑:', path) print('dijkstra方法尋找最短距離:') distance=nx.dijkstra_path_length(G, source=0, target=7) print('節點0到7的距離爲:', distance) 

  •  最小生成樹

定義:一個有 n 個結點的連通圖的生成樹是原圖的極小連通子圖,且包含原圖中的全部 n 個結點,而且有保持圖連通的最少的邊。 

 示例:

def prim(G, s): dist = {}   # dist記錄到節點的最小距離
    parent = {} # parent記錄最小生成樹的雙親表
    Q = list(G.nodes()) # Q包含全部未被生成樹覆蓋的節點
    MAXDIST = 9999.99    # MAXDIST表示正無窮,即兩節點不鄰接

    # 初始化數據
    # 全部節點的最小距離設爲MAXDIST,父節點設爲None
    for v in G.nodes(): dist[v] = MAXDIST parent[v] = None # 到開始節點s的距離設爲0
    dist[s] = 0 # 不斷從Q中取出「最近」的節點加入最小生成樹
    # 當Q爲空時中止循環,算法結束
    while Q: # 取出「最近」的節點u,把u加入最小生成樹
        u = Q[0] for v in Q: if (dist[v] < dist[u]): u = v Q.remove(u) # 更新u的鄰接節點的最小距離
        for v in G.adj[u]: if (v in Q) and (G[u][v]['weight'] < dist[v]): parent[v] = u dist[v] = G[u][v]['weight'] # 算法結束,以雙親表的形式返回最小生成樹
    return parent
import matplotlib.pyplot as plt import networkx as nx g_data = [(1, 2, 1.3), (1, 3, 2.1), (1, 4, 0.9), (1, 5, 0.7), (1, 6, 1.8), (1, 7, 2.0), (1, 8, 1.8), (2, 3, 0.9), (2, 4, 1.8), (2, 5, 1.2), (2, 6, 2.8), (2, 7, 2.3), (2, 8, 1.1), (3, 4, 2.6), (3, 5, 1.7), (3, 6, 2.5), (3, 7, 1.9), (3, 8, 1.0), (4, 5, 0.7), (4, 6, 1.6), (4, 7, 1.5), (4, 8, 0.9), (5, 6, 0.9), (5, 7, 1.1), (5, 8, 0.8), (6, 7, 0.6), (6, 8, 1.0), (7, 8, 0.5)] def draw(g): pos = nx.spring_layout(g) nx.draw(g, pos, \ arrows=True, \ with_labels=True, \ nodelist=g.nodes(), \ style='dashed', \ edge_color='b', \ width=2, \ node_color='y', \ alpha=0.5) plt.show() g = nx.Graph()

tree = prim(g, 1) mtg = nx.Graph() mtg.add_edges_from(tree.items()) mtg.remove_node(None) draw(mtg)

 

  • 最大聯通子圖及聯通子圖規模排序

import matplotlib.pyplot as plt import networkx as nx G=nx.path_graph(4) G.add_path([10,11,12]) nx.draw(G,with_labels=True,label_size=1000,node_size=1000,font_size=20) plt.show() #[print(len(c)) for c in sorted(nx.connected_components(G),key=len,reverse=True)]
for c in sorted(nx.connected_components(G),key=len,reverse=True): print(c)      #看看返回來的是什麼?結果是{0,1,2,3}
    print(type(c))   #類型是set
    print(len(c))   #長度分別是4和3(由於reverse=True,降序排列)
 largest_components=max(nx.connected_components(G),key=len)  # 高效找出最大的聯通成分,其實就是sorted裏面的No.1
print(largest_components)  #找出最大聯通成分,返回是一個set{0,1,2,3}
print(len(largest_components))  #4

{0, 1, 2, 3} <class 'set'>
4 {10, 11, 12} <class 'set'>
3 {0, 1, 2, 3} 4

   

參考資料:

http://yoghurt-lee.online/2017/03/30/graph-visible/

http://blog.sciencenet.cn/home.php?mod=space&uid=404069&do=blog&id=337442

http://www.cnblogs.com/kaituorensheng/p/5423131.html#_label3

http://baiyejianxin.iteye.com/blog/1764048

https://zhuanlan.zhihu.com/p/33616557

https://blog.csdn.net/qq_31192383/article/details/53748129

https://blog.csdn.net/newbieMath/article/details/73800374

http://osask.cn/front/ask/view/565531

相關文章
相關標籤/搜索