【Python基礎(chǔ)】利用 Python 搞定精美網(wǎng)絡(luò)圖!
作者:葉庭云? ? ?編輯:Lemon? ? ??出品:Python數(shù)據(jù)之道
PS:本文所使用的數(shù)據(jù)源以及代碼文件,可以在文末獲取
二、NetworkX 的安裝
pip install networkx -i http://pypi.douban.com/simple --trusted-host pypi.douban.com
三、NetworkX 基礎(chǔ)知識(shí)
1. 創(chuàng)建圖
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()

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)用布局
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()
輸出圖的全部節(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)分析

1. 提取數(shù)據(jù)
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')
import pandas as pd
df = pd.read_excel('samples.xlsx')
df.info()

2. 畫(huà)網(wǎng)絡(luò)圖
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()

(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()

(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()

作者簡(jiǎn)介
葉庭云
個(gè)人格言: 熱愛(ài)可抵歲月漫長(zhǎng)
CSDN博客: https://blog.csdn.net/fyfugoyfa/
往期精彩回顧
