«Это 25-й день моего участия в ноябрьском испытании обновлений. Ознакомьтесь с подробностями события:Вызов последнего обновления 2021 г."
Практикуйте визуализацию социальных сетей с помощью python-networkx
01 Используйте networkx, чтобы создать графовую сетевую модель
- Создайте граф с networkx, добавьте узлы и ребра
- Просмотр матрицы смежности/таблицы смежности/тепловой карты графика
- Расширение возможностей графической сети
- Графическая сетевая статистика (степень выхода и степень входа, кратчайший путь)
пакет гида
import networkx as nx
import matplotlib.pyplot as plt
import collections
import random
import numpy as np
from pylab import rcParams
import warnings
warnings.filterwarnings("ignore")
# 支持中文
plt.rcParams['font.sans-serif'] = ['SimHei'] # 用来正常显示中文标签
plt.rcParams['axes.unicode_minus'] = False # 用来正常显示负号
добавить узел
# 添加结点
G = nx.Graph() # 创建一个空的无向图 创建有向图使用nx.DiGraph()
G.add_node(1) # 创建单个节点
G.add_nodes_from(range(10)) # 创建一组节点
nx.draw(G,node_color="darkblue")
добавить преимущество
G.add_edge(1,2)
e = [(2,3),(9,3),(8,4),(3,5),(8,6),(0,8),(1,9)]
G.add_edges_from(e)
nx.draw(G,with_labels=True,node_color="darkblue",font_color="white")
вывести матрицу смежности и список смежности
# 打印邻接矩阵
print("邻接矩阵")
print(nx.adjacency_matrix(G))
print("="*50)
print("邻接表")
for i in G.adj.items():
print(i)
Тепловая карта
# 邻接矩阵的热力图:反应稀疏程度
print(nx.to_numpy_matrix(G)) #转换邻接矩阵为numpy格式
plt.imshow(nx.to_numpy_matrix(G)) #创建2维热力图
cbar = plt.colorbar() #--> 设置colorbar热力图题注
cbar.set_ticks([0,1]) #--> 设置colorbar刻度范围
cbar.ax.set_yticklabels(['Zero','One'],) #--设置colorbar刻度轴首尾坐标名
cbar.set_label('link', rotation=0) #--设置colorbar坐标名
plt.xlabel('node idx') #--设置 x 轴
plt.ylabel('node idx') #--设置 y 轴
наделение полномочиями
# 赋权
for e in G.edges():
G[e[0]][e[1]]['weight'] = random.uniform(0, 1) # 使用uniform分布给已存在的关系重新赋权
print(nx.to_numpy_matrix(G))
plt.imshow(nx.to_numpy_matrix(G))
cbar = plt.colorbar() #--> 设置colorbar热力图题注
cbar.set_ticks([0,1]) #--> 设置colorbar刻度范围
cbar.ax.set_yticklabels(['Zero','One'],) #--设置colorbar刻度轴首尾坐标名
cbar.set_label('link', rotation=0) #--设置colorbar坐标名
plt.xlabel('node idx') #--设置 x 轴
plt.ylabel('node idx') #--设置 y 轴
сетевая статистика
##### 网络统计量
# 度
G =nx.karate_club_graph() # 创建一个空手道成员俱乐部图 :这是一个非常有名的社交网络图
degree_sequence = sorted([d for n, d in G.degree()], reverse=True) # 保存每个结点的度,并按降序排列
print("度 排列", degree_sequence)
print("= "*50)
degreeCount = collections.Counter(degree_sequence) # 计算每种度的数目
print("度 频率", degreeCount)
print("= "*50)
deg, cnt = zip(*degreeCount.items()) # 创建一个迭代器
rcParams['figure.figsize'] = 12, 8 # 设置画板全局大小
fig, ax = plt.subplots() # 创建子图
plt.bar(deg, cnt, width=0.80, color='darkblue')
plt.title("度 直方图")
plt.ylabel("频率")
plt.xlabel("度")
plt.axes([0.4, 0.4, 0.5, 0.5])
plt.axis('off')
ax.set_xticks([d + 0.4 for d in deg])
ax.set_xticklabels(deg)
pos = nx.spring_layout(G) #-- 设置网络布局
nx.draw_networkx_nodes(G, pos, node_color= 'darkblue',node_size=20) # 画图
nx.draw_networkx_edges(G, pos, alpha=0.5) # 画边
plt.show()
print('无向图的度均值:', np.mean(G.degree()))
Средняя степень неориентированного графа: 10,544117647058824
кратчайший путь
# 最短路径
R = nx.karate_club_graph()
source=14 # 选一个点做起点
target=16 # 选一个点做终点
# 最短路径作图函数
def short_path_plot(G,source,target):
pos = nx.spring_layout(G) #-- 设置网络布局
nx.draw(G,pos,node_color='k', with_labels=True, font_color='white') #-- 画图结构
path = nx.shortest_path(G,source=14,target=16) #-- 调用shortest path计算最短路径
print("最短路径:",path)
path_edges = list(zip(path,path[1:])) #-- 创建最短路径边
nx.draw_networkx_nodes(G,pos,nodelist=path,node_color='r', label=True) #-- 画结点
nx.draw_networkx_edges(G,pos,edgelist=path_edges,edge_color='r',width=10) #--画边
plt.axis('equal')
plt.show()
return
#调用函数
short_path_plot(R,source,target)
02 Структура сети
- случайный граф
- модель маленького мира
- безмасштабная сеть
# 下载 幂律分布 包
# !pip install powerlaw
import re
import powerlaw
import seaborn as sns
from operator import itemgetter
# 直方图绘制
def draw_hist_network(G):
degree_sequence = sorted([d for n, d in G.degree()], reverse=True)
degreeCount = collections.Counter(degree_sequence)
deg, cnt = zip(*degreeCount.items())
rcParams['figure.figsize'] = 10, 5
fig, ax = plt.subplots()
plt.bar(deg, cnt, width=0.80, color='darkblue')
plt.title("度 直方图")
plt.ylabel("频率")
plt.xlabel("度")
ax.set_xticks([d + 0.4 for d in deg])
ax.set_xticklabels(deg)
plt.axes([0.4, 0.4, 0.5, 0.5])
Gcc = G.subgraph(sorted(nx.connected_components(G), key=len, reverse=True)[0])
pos = nx.spring_layout(G)
plt.axis('off')
nx.draw_networkx_nodes(G, pos, node_color= 'darkblue',node_size=20)
nx.draw_networkx_edges(G, pos, alpha=0.4)
plt.show()
pass
# 网络绘制
def draw_network(G,name):
plt.title(name)
pos = nx.circular_layout(G)
nx.draw_networkx_nodes(G, pos, node_color= 'darkblue',node_size=20)
nx.draw_networkx_edges(G, pos, alpha=0.4)
plt.axis('off')
plt.show()
pass
случайный граф
# 生成随机图
nodes_n=50
degree=20
simulation_number=10
rcParams['figure.figsize'] = 5, 5
#连通率 = 0.01:
#------------------------------
G = nx.random_regular_graph(degree,nodes_n) #<-- Generate the Small World Network
draw_network(G,name="随机正太分布图")
Сеть Малого Мира
# 小世界网络
nodes_n=1000
degree=20
rcParams['figure.figsize'] = 5, 5
#简单的小世界模型------------------------------
G = nx.watts_strogatz_graph(20,5,p=0.01) #<-- 生成小世界模型
draw_network(G,name="小世界模型")
#连通率 = 0.01:
#------------------------------
G = nx.watts_strogatz_graph(nodes_n,degree, p = 0.01) #<-- 生成小世界模型
draw_hist_network(G)
#连通率 = 0.05:
#------------------------------
G = nx.watts_strogatz_graph(nodes_n,degree, p = 0.05) #<-- 生成小世界模型
draw_hist_network(G)
#连通率 = 0.1:
#------------------------------
G = nx.watts_strogatz_graph(nodes_n,degree, p = 0.1) #<-- 生成小世界模型
draw_hist_network(G)
безмасштабная сеть
Безмасштабные сети демонстрируют степенное распределение
# 无标度网络
node_n = 100000 #-- 节点数
m=3 #-- 从新节点附加到现有节点的边缘数
G = nx.barabasi_albert_graph(node_n, m)
# draw_network(G,name="无标度网络") # 100000结点绘图很慢很占内存
degree_freq = nx.degree_histogram(G)
degrees = range(len(degree_freq))
plt.figure(figsize=(12, 8))
plt.loglog(degrees[m:], degree_freq[m:],'go-')
plt.xlabel('度', fontsize = 'x-large')
plt.ylabel('频率', fontsize = 'x-large')
plt.show()
03 Измерение узлов — Центральность
Что такое центральность?
Центральность — это термин, описывающий важность отдельных узлов в графе. Для того, чтобы ответить на вопрос «Какой узел является самым важным узлом (вершиной) в графе?», было проведено большое количество экспериментов, и список экспериментов выглядит следующим образом:
- Центральность степени
- Промежуточность
- Близость
- Центральность собственного вектора
- Кац Центральность
Абсолютная центральность используется для точечной центральности/центральности промежуточного положения/центральности близости.
import pandas as pd
import matplotlib.colors as mcolors
from pylab import rcParams
Zachary Karate Club — это широко используемая социальная сеть, в которой узлы представляют членов клуба карате, а ребра представляют отношения между членами.
# Zachary 空手道俱乐部
G = nx.karate_club_graph()
pos = nx.circular_layout(G) #-- 圆盘布局
nodes = nx.draw_networkx_nodes(G, pos, node_size=400,node_color='White',edgecolors='b')
nodes.set_norm(mcolors.SymLogNorm(linthresh=0.03, linscale=2))
labels = {i:i for i in G.nodes()}
labels = nx.draw_networkx_labels(G, pos, labels, font_size=12)
edges = nx.draw_networkx_edges(G, pos, edge_color = 'grey')
plt.axis('off')
plt.show()
def draw(G, pos, measures, measure_name):
nodes = nx.draw_networkx_nodes(G, pos, node_size=400, cmap=plt.cm.plasma,
node_color=list(measures.values()),
nodelist=list(measures.keys()))
nodes.set_norm(mcolors.SymLogNorm(linthresh=0.03, linscale=1))
labels = nx.draw_networkx_labels(G, pos, font_color='white')
edges = nx.draw_networkx_edges(G, pos)
plt.title(measure_name,size=18)
cbar = plt.colorbar(nodes)
cbar.set_label('中心度权重', rotation=0)
plt.axis('off')
plt.show()
pass
точечная центральность
# 点度中心度 Degree Centrality
draw(G, pos,nx.degree_centrality(G),'点度中心度')
промежуточность
# 中介中心度 Betweenness Centrality
draw(G, pos, nx.betweenness_centrality(G), '中介中心度')
близость
# 接近中心度 Closeness Centrality
draw(G, pos, nx.closeness_centrality(G), '接近中心度')
Центральность собственного вектора
# 特征向量中心度 Eigenvector Centrality
draw(G, pos, nx.eigenvector_centrality(G), '特征向量中心度')
Кац Центральность
# 卡茨中心度 Katz Centrality
draw(G, pos, nx.katz_centrality(G, alpha=0.1, beta=1.0), '卡茨中心度')
#创建一个pandas表比较各种中心度:
dataset1=[]
for k in nx.degree_centrality(G).keys():
dataset1.append([k,nx.degree_centrality(G)[k],nx.katz_centrality(G)[k],nx.eigenvector_centrality(G)[k],
nx.closeness_centrality(G)[k],nx.betweenness_centrality(G)[k]])
rcParams['figure.figsize'] = 5, 5
sns.set(style="ticks")
#创建dataframe:
df=pd.DataFrame(dataset1,columns=['id',
'Degree centrality','Katz centrality','Eigenvector centrality',
'Clossness centrality','Betweenness centrality'])
#输出 变量两两之间的关系:
sns.pairplot(df)
04. Общее измерение
- плотность
- центральный потенциал
# 密度
G = nx.karate_club_graph()
print('karate_club_graph图 密度:', nx.density(G))
G = nx.watts_strogatz_graph(21,7,p=0.05) #<-- 生成小世界模型
print('生成的小世界模型 密度:', nx.density(G))
Плотность графика karate_club_graph: 0,13903743315508021 Сгенерированная модель маленького мира Плотность: 0,3
плотность
1. Плотность
Плотность неориентированного графа равнаПлотность направленного графикавn
количество узлов в Gm
— количество ребер в G.
Граф без ребер имеет плотность 0, полный граф имеет плотность 1, а мультиграф может иметь плотность больше 1.
центральный потенциал
2. Центральный потенциал: Центральный потенциал используется для измерения общей центральности сети.
- Сначала найдите максимальное значение центральности MAX в сети;
- Затем вычислите «разницу» между значением MAX и центральностью других точек соответственно;
- Затем вычислите сумму этих «разностей»;
- Наконец, разделите эту сумму на теоретически максимально возможное значение суммы разностей.
Абсолютный центральный потенциал равен
Относительный центральный потенциал равен
# 点度中心势
def Degree_Centralization(G,mode="AD"):
n = nx.number_of_nodes(G) #-- n节点数目
centrality_list = np.array(list(nx.degree_centrality(G).values())) # 中心度列表
max_centrality = max(centrality_list) # 中心度 最大值
if mode=='AD':
degree_centralization = sum(max_centrality - centrality_list) / (n-1)*(n-2)
if mode=='RD':
degree_centralization = sum(max_centrality - centrality_list) / (n-2)
return degree_centralization
G = nx.karate_club_graph()
print('karate_club_graph图 绝对中心势:', Degree_Centralization(G,mode='AD'))
print('karate_club_graph图 相对中心势:', Degree_Centralization(G,mode='RD'))
draw_network(G,name="")
G = nx.watts_strogatz_graph(21,7,p=0.05) #<-- 生成小世界模型
print('生成的小世界模型 绝对中心势:', Degree_Centralization(G,mode='AD'))
print('生成的小世界模型 相对中心势:', Degree_Centralization(G,mode='RD'))
draw_network(G,name="")
05. Агломеративные подгруппы
- Подгруппа конденсата K-ядра
G = nx.karate_club_graph()
nx.core_number(G)
# 输出
{0: 4,
1: 4,
2: 4,
3: 4,
4: 3,
5: 3,
6: 3,
7: 4,
8: 4,
9: 2,
10: 3,
11: 1,
12: 2,
13: 4,
14: 2,
15: 2,
16: 2,
17: 2,
18: 2,
19: 3,
20: 2,
21: 2,
22: 2,
23: 3,
24: 3,
25: 3,
26: 2,
27: 3,
28: 3,
29: 3,
30: 4,
31: 3,
32: 4,
33: 4}
def draw_clu(G, pos, measures, measure_name):
clusters=np.array(list(set(measures.values())))
plt.figure()
nodes = nx.draw_networkx_nodes(G, pos, node_size=250, cmap=mcolors.ListedColormap(plt.cm.Set3(clusters)),
node_color=np.array(list(measures.values()))-1,
nodelist=list(measures.keys()))
print(measures.values())
print(measures.keys())
labels = nx.draw_networkx_labels(G, pos)
edges = nx.draw_networkx_edges(G, pos)
plt.title(measure_name)
rcParams['figure.figsize'] = 12, 8
rcParams['font.sans-serif'] = ['SimHei']
cb = plt.colorbar(nodes,ticks=range(0,len(clusters)), label='子群标签')
cb.ax.tick_params(length=0)
cb.set_ticklabels(list(set(measures.values())))
nodes.set_clim(-0.5, len(clusters)-0.5)
plt.axis('off')
plt.show()
G = nx.karate_club_graph()
pos = nx.spring_layout(G)
draw_clu(G, pos, nx.core_number(G),'k-Core')
draw(G, pos, nx.core_number(G), 'k-Core')
06. Предсказание ссылок
import networkx as nx
import numpy as np
import urllib.request
urllib.request.urlretrieve("http://snap.stanford.edu/data/ca-GrQc.txt.gz", "ca-GrQc.txt.gz")
graph = nx.read_edgelist('ca-GrQc.txt.gz')
graph.order()
draw_network(graph,name="")
degrees = dict(graph.degree())
author = sorted(degrees.items(),key=lambda x: x[1],reverse=True)[500][0]
print('学者 %s 的"度"为 %d' % (author, graph.degree()[author]))
# 获取子图
def get_subgraph(graph, nodes, n=100):
neighbors = set()
for ni in nodes:
neighbors |= set(graph.neighbors(ni))
# plot at least the target node and his neighbors.
result = set(nodes) | neighbors
# add "friends of friends" up to n total nodes.
for x in neighbors:
# how many more nodes can we add?
maxsize = n - len(result)
toadd = set(graph.neighbors(x)) - result
result.update(list(toadd)[:maxsize])
if len(result) > n:
break
return graph.subgraph(result)
subgraph = get_subgraph(graph, [author], n=30)
print('子图有个 %d 结点' % len(subgraph.nodes()))
Ученый 13813 имеет «степень» 13.
Подграф имеет 30 узлов
# 绘制子图
def plot_subgraph(subgraph, target_nodes):
nodes = list(subgraph.nodes())
colors = ['c'] * len(nodes)
for n in target_nodes:
idx = nodes.index(n)
colors[idx] = 'r'
sizes = [800] * len(nodes)
sizes[idx] = 1000
plt.figure(figsize=(8,8))
plt.axis('off')
nx.draw_networkx(subgraph, nodelist=nodes, with_labels=True,
width=.5, node_color=colors,
node_size=sizes, alpha=.5)
plot_subgraph(subgraph, [author])
Кому следует порекомендовать автора 13813 для сотрудничества?
Метод предсказания соединения
- Думайте о задаче прогнозирования ссылок как о проблеме ранжирования в поиске информации.
- Рассчитать новую оценку для каждого ребра.
- Отсортировать все возможные дробные ребра в порядке убывания.
- Выберите самое результативное преимущество .
1.) Кратчайший путь: отприбытьДлина кратчайшего пути.
# 最短路径算法
def rank_by_shortest_path(graph, node):
paths = nx.shortest_path_length(graph, node)
return sorted(paths.items(), key=lambda x: x[1])
shortest_paths = rank_by_shortest_path(graph, author)
print('最短路径 top-20 :')
shortest_paths[:20]
print("以作者13813为起始点,在网络中最短路径为2的合作者有%s位" % len([s for s in shortest_paths if s[1] == 2]))
print('链接预测 top-10 :')
[s for s in shortest_paths if s[1] == 2][:10]
Взяв за отправную точку автора 13813, мы получим 57 соавторов с кратчайшим путем 2 в сети.
визуализация, рекомендательный эффект
pair = set([author, '5227','5543','10931','639','18736'])
plot_subgraph(get_subgraph(graph, pair, n=30), pair)
Другой способ: еслииМного соавторов с соавторами, тоискорее всего в соавторстве
2.) жаккард:
def rank_by_jaccard(graph, node):
neighbors = set(graph.neighbors(node))
scores = []
for n in graph.nodes():
neighbors2 = set(graph.neighbors(n))
scores.append((n, len(neighbors & neighbors2) / len(neighbors | neighbors2)))
return sorted(scores, key=lambda x: x[1], reverse=True)
common_jaccard = rank_by_jaccard(graph, author)
common_jaccard[:20]
plt.plot(sorted([x[1] for x in common_jaccard if x[1] > 0.]))
plt.show()
def dataframe_scores(scores_list, names, n):
ids = set()
for scores in scores_list:
ids.update([x[0] for x in scores[:n]])
print('jaccard算法链接预测的 top %d' % (n))
results = []
for id_ in ids:
result = {'id': id_}
for scores, name in zip(scores_list, names):
for rank, (id2, score) in enumerate(scores):
if id2 == id_:
result[name + '_rank'] = rank
result[name + '_score'] = score
break
results.append(result)
headers = ['id']
for name in names:
headers.append(name + '_rank')
headers.append(name + '_score')
return pd.DataFrame(results, columns=headers)
df = dataframe_scores([common_jaccard],['jaccard'],20)
df.sort_values('jaccard_rank').head(10)
pair = set([author, '23204','19204','17559','409','6746'])
plot_subgraph(get_subgraph(graph, pair, n=30), pair)