【Python基础】利用 Python 搞定精美网络图!
作者:葉庭云? ? ?編輯:Lemon? ? ??出品:Python數(shù)據(jù)之道
一、NetworkX 概述
NetworkX 是一個(gè)用 Python 語(yǔ)言開(kāi)發(fā)的圖論與復(fù)雜網(wǎng)絡(luò)建模工具,內(nèi)置了常用的圖與復(fù)雜網(wǎng)絡(luò)分析算法,可以方便的進(jìn)行復(fù)雜網(wǎng)絡(luò)數(shù)據(jù)分析、仿真建模等工作。
Networkx 支持創(chuàng)建簡(jiǎn)單無(wú)向圖、有向圖和多重圖;內(nèi)置許多標(biāo)準(zhǔn)的圖論算法,節(jié)點(diǎn)可為任意數(shù)據(jù);支持任意的邊值維度,功能豐富。主要用于創(chuàng)造、操作復(fù)雜網(wǎng)絡(luò),以及學(xué)習(xí)復(fù)雜網(wǎng)絡(luò)的結(jié)構(gòu)、動(dòng)力學(xué)及其功能。用于分析網(wǎng)絡(luò)結(jié)構(gòu),建立網(wǎng)絡(luò)模型,設(shè)計(jì)新的網(wǎng)絡(luò)算法,繪制網(wǎng)絡(luò)等等。
PS:本文所使用的數(shù)據(jù)源以及代碼文件,可以在文末獲取
二、NetworkX 的安裝
pip install networkx -i http://pypi.douban.com/simple --trusted-host pypi.douban.com三、NetworkX 基礎(chǔ)知識(shí)
1. 創(chuàng)建圖
可以利用 networkx 創(chuàng)建四種圖:Graph 、DiGraph、MultiGraph、MultiDiGraph,分別為無(wú)多重邊無(wú)向圖、無(wú)多重邊有向圖、有多重邊無(wú)向圖、有多重邊有向圖。
import network as nx G = nx.Graph() G = nx.DiGraph() G = nx.MultiGraph() G = nx.MultiDiGraph()2. 網(wǎng)絡(luò)圖的加點(diǎn)和加邊
import networkx as nx import matplotlib.pyplot as plt G = nx.DiGraph() G.add_node('z') # 添加節(jié)點(diǎn)z G.add_nodes_from([1, 2, 3]) # 添加節(jié)點(diǎn) 1 2 3 G.add_edge('x', 'y') # 添加邊 起點(diǎn)為x 終點(diǎn)為y G.add_edges_from([(1, 2), (1, 3), (2, 3)]) # 添加多條邊 # 網(wǎng)絡(luò)圖繪制與顯示 nx.draw(G, with_labels=True) plt.show()運(yùn)行效果如下:
為了讓網(wǎng)絡(luò)圖更美觀可以調(diào)節(jié)?nx.draw()?方法里的參數(shù)
nx.draw(G, pos=nx.random_layout(G), node_color = 'b', edge_color = 'r', with_labels = True, font_size =18, node_size =20)G:待繪制的網(wǎng)絡(luò)圖G
node_size:指定節(jié)點(diǎn)的尺寸大小(默認(rèn)是300)
node_color: 指定節(jié)點(diǎn)的顏色 (可以用字符串簡(jiǎn)單標(biāo)識(shí)顏色,例如'r'為紅色,'g'為綠色這樣)
node_shape: 節(jié)點(diǎn)的形狀(默認(rèn)是圓形,用字符串'o'標(biāo)識(shí))
alpha: 透明度 (默認(rèn)是1.0,不透明,0為完全透明)
width: 邊的寬度 (默認(rèn)為1.0)
edge_color: 邊的顏色(默認(rèn)為黑色)
style: 邊的樣式(默認(rèn)為實(shí)現(xiàn),可選:solid | dashed | dotted | dashdot
with_labels:節(jié)點(diǎn)是否帶標(biāo)簽
font_size: 節(jié)點(diǎn)標(biāo)簽字體大小
font_color: 節(jié)點(diǎn)標(biāo)簽字體顏色(默認(rèn)為黑色)
3. 運(yùn)用布局
circular_layout:節(jié)點(diǎn)在一個(gè)圓環(huán)上均勻分布?
random_layout:節(jié)點(diǎn)隨機(jī)分布?
shell_layout:節(jié)點(diǎn)在同心圓上分布?
spring_layout:用 Fruchterman-Reingold 算法排列節(jié)點(diǎn)(樣子類(lèi)似多中心放射狀)?
spectral_layout:根據(jù)圖的拉普拉斯特征向量排列節(jié)點(diǎn)
繪制網(wǎng)絡(luò)圖實(shí)例如下:
import networkx as nx import matplotlib.pyplot as plt # 初始化一個(gè)有向圖對(duì)象 DG = nx.DiGraph() DG.add_node('X') # 添加節(jié)點(diǎn) 傳入列表 DG.add_nodes_from(['A', 'B', 'C', 'D', 'E']) print(f'輸出圖的全部節(jié)點(diǎn):{DG.nodes}') print(f'輸出節(jié)點(diǎn)的數(shù)量:{DG.number_of_nodes()}') # 添加邊 傳入列表 列表里每個(gè)元素是一個(gè)元組 元組里表示一個(gè)點(diǎn)指向另一個(gè)點(diǎn)的邊 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'輸出邊的數(shù)量:{DG.number_of_edges()}') # 可自定義節(jié)點(diǎn)顏色 colors = ['pink', 'blue', 'green', 'yellow', 'red', 'brown'] # 運(yùn)用布局 pos = nx.circular_layout(DG) # 繪制網(wǎng)絡(luò)圖 nx.draw(DG, pos=pos, with_labels=True, node_size=200, width=0.6, node_color=colors) # 展示圖片 plt.show()運(yùn)行效果如下:
輸出圖的全部節(jié)點(diǎn):['X', 'A', 'B', 'C', 'D', 'E'] 輸出節(jié)點(diǎn)的數(shù)量:6 輸出圖的全部邊:[('X', 'C'), ('A', 'B'), ('A', 'C'), ('A', 'D'), ('D', 'A'), ('E', 'A'), ('E', 'D')] 輸出邊的數(shù)量:7四、利用 NetworkX 實(shí)現(xiàn)關(guān)聯(lián)類(lèi)分析
利用 soccer.csv 中的數(shù)據(jù),使用 Python 的 NetworkX 包按要求進(jìn)行繪圖。
1. 提取數(shù)據(jù)
統(tǒng)計(jì)不同俱樂(lè)部(Club)的球員數(shù)量,從球員最多的五個(gè)俱樂(lè)部抽取 50 名球員信息(球員數(shù)量最多的俱樂(lè)部抽取 30 名,剩下 4 個(gè)俱樂(lè)部各抽取 5 名)構(gòu)成新的 DataFrame,打印其 info()。
import pandas as pd df = pd.read_csv('soccer.csv', encoding='gbk') data = df['Club'].value_counts() # 球員人數(shù)最多的5個(gè)俱樂(lè)部 clubs = list(data.index[:5]) # 球員數(shù)量最多的俱樂(lè)部抽取30名 df1 = df[df['Club'] == clubs[0]].sample(30, axis=0) # 剩下4個(gè)俱樂(lè)部各抽取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) # 合并多個(gè)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() # 抽樣的數(shù)據(jù)保存到excel new_result.to_excel('samples.xlsx')Jupyter Notebook 環(huán)境中讀取 samples.xlsx,打印其 info(),結(jié)果如下:
import pandas as pd df = pd.read_excel('samples.xlsx') df.info()2. 畫(huà)網(wǎng)絡(luò)圖
在提取出的數(shù)據(jù)的基礎(chǔ)上,通過(guò)判斷球員是否屬于同一俱樂(lè)部,繪出隨機(jī)分布網(wǎng)絡(luò)圖、Fruchterman-Reingold 算法排列節(jié)點(diǎn)網(wǎng)絡(luò)圖與同心圓分布網(wǎng)絡(luò)圖。盡可能讓網(wǎng)絡(luò)圖美觀,如為屬于同一俱樂(lè)部的節(jié)點(diǎn)設(shè)置相同的顏色。
將每個(gè)球員當(dāng)作網(wǎng)絡(luò)圖中一個(gè)節(jié)點(diǎn),計(jì)算節(jié)點(diǎn)之間的連通關(guān)系,同屬一個(gè)俱樂(lè)部則連通。
import pandas as pd df = pd.read_excel('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, '節(jié)點(diǎn)編號(hào)': nodes, '所屬俱樂(lè)部': club}) df.to_csv('nodes_info.csv') with open('record.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]: # 屬于同一俱樂(lè)部f.write(f'{nodes[i]}-{nodes[j + 1]}-{datas[i][1]}'+ '\n')(1) 隨機(jī)分布網(wǎng)絡(luò)圖
import networkx as nx import matplotlib.pyplot as plt import pandas as pd from collections importCounter df = pd.read_csv('nodes_info.csv')['所屬俱樂(lè)部'] items = df.values print(Counter(items)) node_colors = [] # 5個(gè)俱樂(lè)部 屬于同一個(gè)俱樂(lè)部的節(jié)點(diǎn)設(shè)置相同顏色 for item in items: if item == 'Free Agents':node_colors.append('red') elif item == 'Real Madrid':node_colors.append('yellow') elif item == 'Chelsea':node_colors.append('blue') elif item == 'FC Barcelona':node_colors.append('green') elif item == 'Manchester Utd':node_colors.append('pink') DG = nx.MultiGraph() DG.add_nodes_from([str(i) for i in range(0, 50)]) DG.nodes() with open('record.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) # 運(yùn)用布局 pos = nx.random_layout(DG) # 節(jié)點(diǎn)隨機(jī)分布 # 繪制網(wǎng)絡(luò)圖 nx.draw(DG, pos, with_labels=True, node_size=200, width=0.6, node_color=node_colors) # 顯示圖片 plt.show()運(yùn)行效果如下:
(2) Fruchterman-Reingold 算法排列節(jié)點(diǎn)網(wǎng)絡(luò)圖
import networkx as nx import matplotlib.pyplot as plt import pandas as pd from collections importCounter df = pd.read_csv('nodes_info.csv')['所屬俱樂(lè)部'] items = df.values print(Counter(items)) node_colors = [] # 5個(gè)俱樂(lè)部 屬于同一個(gè)俱樂(lè)部的節(jié)點(diǎn)設(shè)置相同顏色 for item in items: if item == 'Free Agents':node_colors.append('red') elif item == 'Real Madrid':node_colors.append('yellow') elif item == 'Chelsea':node_colors.append('blue') elif item == 'FC Barcelona':node_colors.append('green') elif item == 'Manchester Utd':node_colors.append('pink') DG = nx.MultiGraph() DG.add_nodes_from([str(i) for i in range(0, 50)]) DG.nodes() with open('record.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) # 運(yùn)用布局 pos = nx.spring_layout(DG) # 用Fruchterman-Reingold算法排列節(jié)點(diǎn)(樣子類(lèi)似多中心放射狀) # 繪制網(wǎng)絡(luò)圖 nx.draw(DG, pos, node_size=10, width=0.6, node_color=node_colors) # 顯示圖片 plt.show()運(yùn)行效果如下:
(3) 同心圓分布網(wǎng)絡(luò)圖
import networkx as nx import matplotlib.pyplot as plt import pandas as pd from collections importCounter df = pd.read_csv('nodes_info.csv')['所屬俱樂(lè)部'] items = df.values print(Counter(items)) node_colors = [] # 5個(gè)俱樂(lè)部 屬于同一個(gè)俱樂(lè)部的節(jié)點(diǎn)設(shè)置相同顏色 for item in items: if item == 'Free Agents':node_colors.append('red') elif item == 'Real Madrid':node_colors.append('yellow') elif item == 'Chelsea':node_colors.append('blue') elif item == 'FC Barcelona':node_colors.append('green') elif item == 'Manchester Utd':node_colors.append('pink') DG = nx.MultiGraph() DG.add_nodes_from([str(i) for i in range(0, 50)]) DG.nodes() with open('record.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) # 運(yùn)用布局 pos = nx.shell_layout(DG) # 節(jié)點(diǎn)在同心圓上分布 # 繪制網(wǎng)絡(luò)圖 nx.draw(DG, pos, with_labels=True, node_size=200, width=0.6, node_color=node_colors) # 顯示圖片 plt.show()運(yùn)行效果如下:
為方便大家練習(xí),可以在公號(hào)「Python數(shù)據(jù)之道」后臺(tái)回復(fù) “網(wǎng)絡(luò)圖” 獲取本文的數(shù)據(jù)和源代碼文件。
作者簡(jiǎn)介
葉庭云
個(gè)人格言: 熱愛(ài)可抵歲月漫長(zhǎng)
CSDN博客: https://blog.csdn.net/fyfugoyfa/
---------End---------
往期精彩回顧適合初學(xué)者入門(mén)人工智能的路線(xiàn)及資料下載機(jī)器學(xué)習(xí)及深度學(xué)習(xí)筆記等資料打印機(jī)器學(xué)習(xí)在線(xiàn)手冊(cè)深度學(xué)習(xí)筆記專(zhuān)輯《統(tǒng)計(jì)學(xué)習(xí)方法》的代碼復(fù)現(xiàn)專(zhuān)輯 AI基礎(chǔ)下載機(jī)器學(xué)習(xí)的數(shù)學(xué)基礎(chǔ)專(zhuān)輯總結(jié)
以上是生活随笔為你收集整理的【Python基础】利用 Python 搞定精美网络图!的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 【NLP】推荐一些NER的英文数据集
- 下一篇: 【面试招聘】社招如何拿到心仪公司的off