一、NetworkX 概述
NetworkX 是一個用 Python 語言開發的圖論與復雜網絡建模工具,內置了常用的圖與復雜網絡分析算法,可以方便的進行復雜網絡數據分析、仿真建模等工作。
Networkx 支持創建簡單無向圖、有向圖和多重圖;內置許多標准的圖論算法,節點可為任意數據;支持任意的邊值維度,功能豐富。主要用於創造、操作復雜網絡,以及學習復雜網絡的結構、動力學及其功能。用於分析網絡結構,建立網絡模型,設計新的網絡算法,繪制網絡等等。
二、NetworkX 的安裝
pip install networkx -i http://pypi.douban.com/simple --trusted-host pypi.douban.com
三、NetworkX 基礎知識 1. 創建圖 可以利用 networkx 創建四種圖: Graph 、DiGraph、MultiGraph、MultiDiGraph,分別為無多重邊無向圖、無多重邊有向圖、有多重邊無向圖、有多重邊有向圖。 import networkx as nx G = nx.Graph() G = nx.DiGraph() G = nx.MultiGraph() G = nx.MultiDiGraph()
2. 網絡圖的加點和加邊 import networkx as nx import matplotlib.pyplot as plt G = nx.DiGraph() G.add_node('z') # 添加節點z G.add_nodes_from([1, 2, 3]) # 添加節點 1 2 3 G.add_edge('x', 'y') # 添加邊 起點為x 終點為y G.add_edges_from([(1, 2), (1, 3), (2, 3)]) # 添加多條邊 # 網絡圖繪制與顯示 nx.draw(G, with_labels=True) plt.show()
為了讓網絡圖更美觀可以調節 nx.draw() 方法里的參數 nx.draw(G, pos=nx.random_layout(G), node_color = 'b', edge_color = 'r', with_labels = True, font_size =18, node_size =20) G:待繪制的網絡圖G node_size:指定節點的尺寸大小(默認是300) node_color: 指定節點的顏色 (可以用字符串簡單標識顏色,例如'r'為紅色,'g'為綠色這樣) node_shape: 節點的形狀(默認是圓形,用字符串'o'標識) alpha: 透明度 (默認是1.0,不透明,0為完全透明) width: 邊的寬度 (默認為1.0) edge_color: 邊的顏色(默認為黑色) style: 邊的樣式(默認為實現,可選: solid | dashed | dotted | dashdot with_labels:節點是否帶標簽 font_size: 節點標簽字體大小 font_color: 節點標簽字體顏色(默認為黑色)
3. 運用布局 circular_layout:節點在一個圓環上均勻分布 random_layout:節點隨機分布 shell_layout:節點在同心圓上分布 spring_layout:用 Fruchterman-Reingold 算法排列節點(樣子類似多中心放射狀) spectral_layout:根據圖的拉普拉斯特征向量排列節點 繪制網絡圖實例如下: import networkx as nx import matplotlib.pyplot as plt # 初始化一個有向圖對象 DG = nx.DiGraph() DG.add_node('X') # 添加節點 傳入列表 DG.add_nodes_from(['A', 'B', 'C', 'D', 'E']) print(f'輸出圖的全部節點:{DG.nodes}') print(f'輸出節點的數量:{DG.number_of_nodes()}') # 添加邊 傳入列表 列表里每個元素是一個元組 元組里表示一個點指向另一個點的邊 DG.add_edges_from([('A', 'B'), ('A', 'C'), ('A', 'D'), ('D', 'A'), ('E', 'A'), ('E', 'D')]) DG.add_edge('X', 'C') print(f'輸出圖的全部邊:{DG.edges}') print(f'輸出邊的數量:{DG.number_of_edges()}') # 可自定義節點顏色 colors = ['pink', 'blue', 'green', 'yellow', 'red', 'brown'] # 運用布局 pos = nx.circular_layout(DG) # 繪制網絡圖 nx.draw(DG, pos=pos, with_labels=True, node_size=200, width=0.6, node_color=colors) # 展示圖片 plt.show()
四、利用 NetworkX 實現關聯類分析
利用 soccer.csv 中的數據,使用 Python 的 NetworkX 包按要求進行繪圖。
1. 提取數據 統計不同俱樂部(Club)的球員數量,從球員最多的五個俱樂部抽取 50 名球員信息(球員數量最多的俱樂部抽取 30 名,剩下 4 個俱樂部各抽取 5 名)構成新的 DataFrame,打印其 info()。 import pandas as pd df = pd.read_csv('E:\\python--networkx\\202010\\soccer.csv', encoding='gbk') data = df['Club'].value_counts() # 球員人數最多的5個俱樂部 clubs = list(data.index[:5]) # 球員數量最多的俱樂部抽取30名 df1 = df[df['Club'] == clubs[0]].sample(30, axis=0) # 剩下4個俱樂部各抽取5名 df2 = df[df['Club'] == clubs[1]].sample(5, axis=0) df3 = df[df['Club'] == clubs[2]].sample(5, axis=0) df4 = df[df['Club'] == clubs[3]].sample(5, axis=0) df5 = df[df['Club'] == clubs[4]].sample(5, axis=0) # 合並多個DataFrame result = pd.concat([df1, df2, df3, df4, df5], axis=0, ignore_index=True) # 打亂DataFrame順序 new_result = result.sample(frac=1).reset_index(drop=True) # new_result.info() # 抽樣的數據保存到excel new_result.to_excel('E:\\samples.xlsx')
Jupyter Notebook 環境中讀取 samples.xlsx,打印其 info(),結果如下: import pandas as pd df = pd.read_excel('E:\\samples.xlsx') df.info()
2. 畫網絡圖 在提取出的數據的基礎上,通過判斷球員是否屬於同一俱樂部,繪出隨機分布網絡圖、Fruchterman-Reingold 算法排列節點網絡圖與同心圓分布網絡圖。盡可能讓網絡圖美觀,如為屬於同一俱樂部的節點設置相同的顏色。 將每個球員當作網絡圖中一個節點,計算節點之間的連通關系,同屬一個俱樂部則連通。 import pandas as pd df = pd.read_excel('E:\\samples.xlsx') df = df.loc[::, ['Name', 'Club']] print(df['Club'].value_counts()) datas = df.values.tolist() name = [datas[i][0] for i in range(len(datas))] nodes = [str(i) for i in range(len(datas))] club = [datas[i][1] for i in range(len(datas))] # print(nodes) df = pd.DataFrame({'姓名': name, '節點編號': nodes, '所屬俱樂部': club}) df.to_csv('E:\\python--networkx\\202010\\nodes_info_1.csv') with open('E:\\python--networkx\\202010\\record_1.txt', 'w') as f: for i in range(len(nodes)): for j in range(i, len(nodes) - 1): if datas[i][1] == datas[j+1][1]: # 屬於同一俱樂部 f.write(f'{nodes[i]}-{nodes[j + 1]}-{datas[i][1]}'+ '\n')
(1) 隨機分布網絡圖 import networkx as nx import matplotlib.pyplot as plt import pandas as pd from collections import Counter df = pd.read_csv('E:\\python--networkx\\202010\\nodes_info_1.csv')['所屬俱樂部'] items = df.values print(Counter(items)) node_colors = [] # 5個俱樂部 屬於同一個俱樂部的節點設置相同顏色 for item in items: if item == 'Free Agents': node_colors.append('red') elif item == 'FC Augsburg': node_colors.append('yellow') elif item == 'RC Deportivo': node_colors.append('blue') elif item == 'FC Barcelona': node_colors.append('green') elif item == 'UD Las Palmas': node_colors.append('pink') DG = nx.MultiGraph() DG.add_nodes_from([str(i) for i in range(0, 50)]) DG.nodes() with open('E:\\python--networkx\\202010\\record_1.txt', 'r') as f: con = f.read().split('\n') edges_list = [] for i in con[:-1]: edges_list.append(tuple(i.split('-')[:2])) print(edges_list) DG.add_edges_from(edges_list) # 運用布局 pos = nx.random_layout(DG) # 節點隨機分布
# 繪制網絡圖 nx.draw(DG, pos, with_labels=True, node_size=200, width=0.6, node_color=node_colors) # 顯示圖片 plt.show()
(2) Fruchterman-Reingold 算法排列節點網絡圖 import networkx as nx import matplotlib.pyplot as plt import pandas as pd from collections import Counter df = pd.read_csv('E:\\python--networkx\\202010\\nodes_info_1.csv')['所屬俱樂部'] items = df.values print(Counter(items)) node_colors = [] # 5個俱樂部 屬於同一個俱樂部的節點設置相同顏色 for item in items: if item == 'Free Agents': node_colors.append('red') elif item == 'FC Augsburg': node_colors.append('yellow') elif item == 'RC Deportivo': node_colors.append('blue') elif item == 'FC Barcelona': node_colors.append('green') elif item == 'UD Las Palmas': node_colors.append('pink') DG = nx.MultiGraph() DG.add_nodes_from([str(i) for i in range(0, 50)]) DG.nodes() with open('E:\\python--networkx\\202010\\record_1.txt', 'r') as f: con = f.read().split('\n') edges_list = [] for i in con[:-1]: edges_list.append(tuple(i.split('-')[:2])) print(edges_list) DG.add_edges_from(edges_list) # 運用布局 pos = nx.spring_layout(DG) # 用Fruchterman-Reingold算法排列節點(樣子類似多中心放射狀) # 繪制網絡圖 nx.draw(DG, pos, node_size=10, width=0.6, node_color=node_colors) # 顯示圖片 plt.show()
(3) 同心圓分布網絡圖 import networkx as nx import matplotlib.pyplot as plt import pandas as pd from collections import Counter df = pd.read_csv('E:\\python--networkx\\202010\\nodes_info_1.csv')['所屬俱樂部'] items = df.values print(Counter(items)) node_colors = [] # 5個俱樂部 屬於同一個俱樂部的節點設置相同顏色 for item in items: if item == 'Free Agents': node_colors.append('red') elif item == 'FC Augsburg': node_colors.append('yellow') elif item == 'RC Deportivo': node_colors.append('blue') elif item == 'FC Barcelona': node_colors.append('green') elif item == 'UD Las Palmas': node_colors.append('pink') DG = nx.MultiGraph() DG.add_nodes_from([str(i) for i in range(0, 50)]) DG.nodes() with open('E:\\python--networkx\\202010\\record_1.txt', 'r') as f: con = f.read().split('\n') edges_list = [] for i in con[:-1]: edges_list.append(tuple(i.split('-')[:2])) print(edges_list) DG.add_edges_from(edges_list) # 運用布局 pos = nx.shell_layout(DG) # 節點在同心圓上分布 # 繪制網絡圖 nx.draw(DG, pos, with_labels=True, node_size=200, width=0.6, node_color=node_colors) # 顯示圖片 plt.show()