前言:下期给我们撷取NetworkX非官方得出的SNSABM事例:FacebookABM[1],以更进一步增进对繁杂互联网基本知识的认知。
那个笔记本电脑包涵了三个SNSABM,主要就是用NetworkX的库继续执行的。简而言之,将对10对个人的facebook圈子里(挚友条目)展开检查审核,以抽取各式各样有用的重要信息。统计数据集能在麻省理工学院的中文网站上[2]找出。除此之外,不可否认,facebook互联网是无向的,没权重股,因为三个采用者可能将只与另三个采用者正式成为一场挚友。从图象预测的视角上看统计数据集:
★ 每一结点代表者三个非官方的facebook采用者,他归属于这六个挚友条目中的三个。
★ 每一边都相关联着归属于那个互联网的三个facebook采用者的情谊。换言之,三个采用者要在facebook上正式成为挚友就能在某一的互联网中相连。
上面得出非官方的jupyter notebook实例标识符:
具体来说,引入必要性的库:
import pandas as pd
import numpy as np
import networkx as nx
import matplotlib.pyplot as plt
from random import randint
从统计数据配置文件读取Minervois统计数据,每一边都是三个LX1,每一边都有三个start_node和三个end_node列:
facebook = pd.read_csv(
"data/facebook_combined.txt.gz",
compression="gzip",
sep=" ",
names=["start_node", "end_node"],
)
创建互联网:
G = nx.from_pandas_edgelist(facebook, "start_node", "end_node")
可视化互联网:即使我们对统计数据的结构没任何真正的感觉,所以让我们从采用random_layout查看互联网,这是最快的布局函数之一。
fig, ax = plt.subplots(figsize=(15, 9))
ax.axis("off")
plot_options = {"node_size": 10, "with_labels": False, "width": 0.15}nx.draw_networkx(G, pos=nx.random_layout(G), ax=ax, **plot_options)
生成的图不是很有用,这种图可视化有时被通俗地称为“毛球”,即使重叠的边会导致纠缠的混乱。
很明显,如果我们想要获得统计数据的感觉,我们需要在定位上施加更多的结构。为此,我们能采用spring_layout函数,它是networkx绘图模块的默认布局函数。spring_layout函数的优点是它考虑了结点和边来计算结点的位置。然而,缺点是那个过程的计算成本要高得多,而且对于有100个结点和1000个边的图来说会非常慢。
由于我们的数据集有超过80k条边,我们将限制spring_layout函数中采用的迭代次数,以减少计算时间。我们还将保存计算出来的布局,以便在将来的可视化中采用它。
pos = nx.spring_layout(G, iterations=15, seed=1721)
fig, ax = plt.subplots(figsize=(15, 9))
ax.axis("off")
nx.draw_networkx(G, pos=pos, ax=ax, **plot_options)
★ 获取互联网的基本拓扑属性:
# 结点数量
G.number_of_nodes()
4039
# Minervois数量
G.number_of_edges()
88234
np.mean([d for _, d in G.degree()])
43.69101262688784
shortest_path_lengths = dict(nx.all_pairs_shortest_path_length(G))
# Length of shortest path between nodes 0 and 42
shortest_path_lengths[0][42]
1
diameter = max(nx.eccentricity(G, sp=shortest_path_lengths).values())
diameter
8
# Compute the average shortest path length for each node
average_path_lengths = [
np.mean(list(spl.values())) for spl in shortest_path_lengths.values()
]
# The average over all nodes
np.mean(average_path_lengths)3.691592636562027
上述结果代表者了所有结点对最短路径长度的平均值:为了从三个结点到达另三个结点,平均大约要遍历3.6条边。
上面的度量捕获了关于互联网的有用重要信息,但是像平均值这样的度量只代表者了分布的三个时刻。我们能通过预先计算的dict-of-dicts构建三个最短路径长度分布的可视化:
# We know the maximum shortest path length (the diameter), so create an array
# to store values from 0 up to (and including) diameter
path_lengths = np.zeros(diameter + 1, dtype=int)
# Extract the frequency of shortest path lengths between two nodes
for pls in shortest_path_lengths.values():
pl, cnts = np.unique(list(pls.values()), return_counts=True)
path_lengths[pl] += cnts
# Express frequency distribution as a percentage (ignoring path lengths of 0)
freq_percent = 100 * path_lengths[1:] / path_lengths[1:].sum()
# Plot the frequency distribution (ignoring path lengths of 0) as a percentage
fig, ax = plt.subplots(figsize=(15, 8))
ax.bar(np.arange(1, diameter + 1), height=freq_percent)
ax.set_title(
"Distribution of shortest path length in G", fontdict={"size": 35}, loc="center"
)
ax.set_xlabel("Shortest Path Length", fontdict={"size": 22})
ax.set_ylabel("Frequency (%)", fontdict={"size": 22})
大多数最短路径的长度是从2条边到5条边的长度。除此之外,对于一对结点来说,其最短路径长度为8(直径长度)的可能将性非常小,即使其可能将性小于0.1%。
计算图的密度,显然,这是三个非常稀疏的图。以及图包涵组件的数量,正如预期的那样,那个互联网由三个巨大的组件组成:
nx.density(G)
0.010819963503439287
nx.number_connected_components(G)1
接下来,对facebook互联网的中心性指标展开研究:
★ 度中心性:度中心性简单地根据每一结点所拥有的链接数量分配三个重要分数。在那个预测中,这意味着三个结点的中心性程度越高,相连到该结点的边越多,因此该结点的邻居结点(facebook挚友)也越多。事实上,三个结点的中心性程度就是它所相连的结点的分数。换言之,它是互联网中某一结点与交友关系的百分比。
具体来说,我们找出中心度最高的结点。其中,8个度中心性最高的结点及其度中心性如下图所示:
degree_centrality = nx.centrality.degree_centrality(G)
# save results in a variable to use again
(sorted(degree_centrality.items(), key=lambda item: item[1], reverse=True))[:8]
[(107, 0.258791480931154),
(1684, 0.1961367013372957),
(1912, 0.18697374938088163),
(3437, 0.13546310054482416),
(0, 0.08593363051015354),
(2543, 0.07280832095096582),
(2347, 0.07206537890044576), (1888, 0.0629024269440317)]
现在我们还能看到中心度最高的结点的邻居数量:
(sorted(G.degree, key=lambda item: item[1], reverse=True))[:8]
[(107, 1045),
(1684, 792),
(1912, 755),
(3437, 547),
(0, 347),
(2543, 294),
(2347, 291),
(1888, 254)]
绘制出程度中心性的分布:
plt.figure(figsize=(15, 8))
plt.hist(degree_centrality.values(), bins=25)
plt.xticks(ticks=[0, 0.025, 0.05, 0.1, 0.15, 0.2]) # set the x axis ticks
plt.title("Degree Centrality Histogram ", fontdict={"size": 35}, loc="center")
plt.xlabel("Degree Centrality", fontdict={"size": 20})
plt.ylabel("Counts", fontdict={"size": 20})
现在让我们根据结点的大小来检查中心度最高的采用者:
node_size = [
v * 1000 for v in degree_centrality.values()
] # set up nodes size for a nice graph representation
plt.figure(figsize=(15, 8))
nx.draw_networkx(G, pos=pos, node_size=node_size, with_labels=False, width=0.15)
plt.axis("off")
★ 介数中心性:
betweenness_centrality = nx.centrality.betweenness_centrality(
G
) # save results in a variable to use again
(sorted(betweenness_centrality.items(), key=lambda item: item[1], reverse=True))[:8]
[(107, 0.4805180785560152),
(1684, 0.3377974497301992),
(3437, 0.23611535735892905),
(1912, 0.2292953395868782),
(1085, 0.14901509211665306),
(0, 0.14630592147442917), (698, 0.11533045020560802), (567, 0.09631033121856215)]
plt.figure(figsize=(15, 8))
plt.hist(betweenness_centrality.values(), bins=100)
plt.xticks(ticks=[0, 0.02, 0.1, 0.2, 0.3, 0.4, 0.5]) # set the x axis ticks
plt.title("Betweenness Centrality Histogram ", fontdict={"size": 35}, loc="center")
plt.xlabel("Betweenness Centrality", fontdict={"size": 20})
plt.ylabel("Counts", fontdict={"size": 20})
按照介数值的大小展开互联网可视化:
node_size = [
v * 1200 for v in betweenness_centrality.values()
] # set up nodes size for a nice graph representation
plt.figure(figsize=(15, 8))
nx.draw_networkx(G, pos=pos, node_size=node_size, with_labels=False, width=0.15)
plt.axis("off")
★ 接近度中心性:
closeness_centrality = nx.centrality.closeness_centrality(
G
) # save results in a variable to use again
(sorted(closeness_centrality.items(), key=lambda item: item[1], reverse=True))[:8]
[(107, 0.45969945355191255),
(58, 0.3974018305284913),
(428, 0.3948371956585509),
(563, 0.3939127889961955),
(1684, 0.39360561458231796),
(171, 0.37049270575282134),
(348, 0.36991572004397216), (483, 0.3698479575013739)]
# 除此之外,三个某一结点v到任何其他结点的平均距离也能很容易地用公式求出:1 / closeness_centrality[107]2.1753343239227343
plt.figure(figsize=(15, 8))
plt.hist(closeness_centrality.values(), bins=60)
plt.title("Closeness Centrality Histogram ", fontdict={"size": 35}, loc="center")
plt.xlabel("Closeness Centrality", fontdict={"size": 20})
plt.ylabel("Counts", fontdict={"size": 20})
node_size = [
v * 50 for v in closeness_centrality.values()
] # set up nodes size for a nice graph representation
plt.figure(figsize=(15, 8))
nx.draw_networkx(G, pos=pos, node_size=node_size, with_labels=False, width=0.15)
plt.axis("off")
以及特征向量中心性等中心性指标,用类似的方式即可获取上述图象。
★ 集聚系数:
# 平均集聚系数
nx.average_clustering(G)
0.6055467186200876
plt.figure(figsize=(15, 8))
plt.hist(nx.clustering(G).values(), bins=50)
plt.title("Clustering Coefficient Histogram ", fontdict={"size": 35}, loc="center")
plt.xlabel("Clustering Coefficient", fontdict={"size": 20})
plzt.ylabel("Counts", fontdict={"size": 20})
★ 桥:
nx.has_bridges(G)
True
# 输出桥的数量
bridges = list(nx.bridges(G))len(bridges)
75
plt.figure(figsize=(15, 8))nx.draw_networkx(G, pos=pos, node_size=10, with_labels=False, width=0.15)nx.draw_networkx_edges( G, pos, edgelist=local_bridges, width=0.5, edge_color="lawngreen") # green color for local bridgesnx.draw_networkx_edges( G, pos, edgelist=bridges, width=0.5, edge_color="r") # red color for bridgesplt.axis("off")
★ 互联网关联系数:
nx.degree_assortativity_coefficient(G)0.06357722918564943nx.degree_pearson_correlation_coefficient(G) 0.06357722918564918
★ 互联网社区:社区是一组结点,因此组内的结点相连
的边要比组间相连的边多得多。该互联网将采用两种不
同的算法展开社区检测。
具体来说,采用半同步标签传播方法检测社区:
该函数自行确定将检测到的社区数量。现在将遍历社
区,并创建三个颜色条目,为归属于同三个社区的结点
包涵相同的颜色。除此之外,社区的数量也被打印出来:
colors = ["" for x in range(G.number_of_nodes())] # initialize colors listcounter = 0for com in nx.community.label_propagation_communities(G): color = "#X" % randint(0, 0xFFFFFF) # creates random RGB color counter += 1 for node in list( com ): # fill colors list with the particular color for the community nodes colors[node] = colorcounter44plt.figure(figsize=(15, 9))plt.axis("off")nx.draw_networkx( G, pos=pos, node_size=10, with_labels=False, width=0.15, node_color=colors)
其次,采用异步流体团体算法:
colors = ["" for x in range(G.number_of_nodes())]for com in nx.community.asyn_fluidc(G, 8, seed=0): color = "#X" % randint(0, 0xFFFFFF) # creates random RGB color for node in list(com): colors[node] = colorplt.figure(figsize=(15, 9))plt.axis("off")nx.draw_networkx( G, pos=pos, node_size=10, with_labels=False, width=0.15, node_color=colors)[1] https://networkx.org/nx-guides/content/exploratory_notebooks/facebook_notebook.html#id2[2] http://snap.stanford.edu/data/ego-Facebook.html
本文采用 文章同步助手 同步