跳至内容
Python
数据分析

使用 Python 进行社会网络分析

当今的网络已成为我们日常生活的一部分。让我们用 NetworkX 在 Python 中学习如何可视化并理解社交网络。
Amita Kapoor's photo
Amita Kapoor
已更新 · 12分钟 阅读

使用 AI 探索

ChatGPTClaudePerplexity

创建您的免费账户

实践并学习路径你的进步。

使用 Google 继续
继续操作即表示您接受我们的《使用条款》和《隐私政策》,并同意您的数据存储在美国。

如果您想学习网络分析,请参加 DataCamp 的课程 Network Analysis in Python (Part 1)。

网络无处不在:公路网络、社交媒体上的好友与关注者网络、办公室同事网络。从传播有用信息到影响全国选举,它们在我们的日常生活中扮演着重要角色。能够分析这些网络并据此做出明智决策,是每位数据分析师都应具备的一项技能。

本教程旨在使用 Python 和 NetworkX(一个用于研究复杂网络结构、动态与功能的 Python 库)教授社会网络分析(SNA)。本教程假设读者已熟悉 Python 的基本语法,不要求具备 SNA 的先验知识。

简介

我们先来明确什么是社会网络。下图展示的是宝莱坞演员构成的网络,演员为节点。如果他们至少在一部电影中合作过,就用实线相连。

bollywood actors

由此可见,Amitabh Bachchan 和 Abhishek Bachchan 与网络中的所有演员都有过合作,而 Akshay Kumar 只与两位 Bachchan 合作过。很有意思吧!

这同样是一个社会网络。任何由个体构成、并以连接来表示个体之间关系的网络,都是社会网络。分析这类网络可以帮助我们深入了解网络中的人,例如谁是真正的影响者、谁连接最多等。

每个网络由以下部分组成:

  • 节点(Nodes):我们要构建网络的个体。上述示例中的演员。
  • 边(Edges):节点之间的连接。它表示网络中节点之间的关系。在我们的示例中,关系是演员们曾经合作过。

使用 NetworkX 创建网络

网络有许多类型。我们将使用 NetworkX 来构建并分析这些不同的网络。首先,您需要安装 networkX:您可以使用:

pip install networkx

或者如果您使用 Anaconda

conda install -c anaconda networkx

这将安装最新版本的 networkx。本教程中的代码基于 Python=3.5、NetworkX=2.0 版本。

对称网络

我们上面创建的演员网络是一个对称网络,因为“在同一部电影中合作”这一关系是对称的。如果 A 与 B 有关,那么 B 也与 A 有关。让我们在 NetworkX 中创建上图所示的网络。

我们将使用 Graph() 方法来创建一个新网络,并用 add_edge() 在两个节点之间添加一条边。

import networkx as nx
G_symmetric = nx.Graph()
G_symmetric.add_edge('Amitabh Bachchan','Abhishek Bachchan')
G_symmetric.add_edge('Amitabh Bachchan','Aamir Khan')
G_symmetric.add_edge('Amitabh Bachchan','Akshay Kumar')
G_symmetric.add_edge('Amitabh Bachchan','Dev Anand')
G_symmetric.add_edge('Abhishek Bachchan','Aamir Khan')
G_symmetric.add_edge('Abhishek Bachchan','Akshay Kumar')
G_symmetric.add_edge('Abhishek Bachchan','Dev Anand')
G_symmetric.add_edge('Dev Anand','Aamir Khan')

现在我们使用 nx.draw_networkx(G_symmetric) 将刚刚构建的网络可视化。

visualized network

非对称网络

如果节点之间的关系是“子女”,那么关系就不再对称。如果 A 是 B 的孩子,那么 B 不是 A 的孩子。这样的网络中,关系是非对称的(A 与 B 有关并不必然意味着 B 也与 A 有关),称为非对称网络。我们可以使用 DiGraph 方法(有向图 的缩写)在 NetworkX 中构建非对称网络。让我们创建一个非对称图。

G_asymmetric = nx.DiGraph()
G_asymmetric.add_edge('A','B')
G_asymmetric.add_edge('A','D')
G_asymmetric.add_edge('C','A')
G_asymmetric.add_edge('D','E')

现在我们来可视化它。我们可以像之前那样使用 draw_networkx() 函数。不过,有时节点可能不会分散开来,在绘制的网络中不易区分。为了解决这个问题,我们可以使用布局算法来强制布局,从而将节点摆放在更容易区分的位置。我们可以先使用 spring_layout() 函数,然后再调用 draw_networkx() 函数来实现。

nx.spring_layout(G_asymmetric)
nx.draw_networkx(G_asymmetric)

下图展示了使用与不使用布局命令的网络。使用布局命令生成的图更清晰。

visualized network 2

加权网络

到目前为止,我们使用的都是无权网络,但也可能存在带权重的网络。例如,在最初的网络中,如果把合作拍摄的电影数量作为权重,我们就会得到一个加权网络。让我们再次构建演员网络,不过这次我们为网络添加权重:每条边的权重表示他们合作过的电影数量。

G_weighted = nx.Graph()
G_weighted.add_edge('Amitabh Bachchan','Abhishek Bachchan', weight=25)
G_weighted.add_edge('Amitabh Bachchan','Aaamir Khan', weight=8)
G_weighted.add_edge('Amitabh Bachchan','Akshay Kumar', weight=11)
G_weighted.add_edge('Amitabh Bachchan','Dev Anand', weight=1)
G_weighted.add_edge('Abhishek Bachchan','Aaamir Khan', weight=4)
G_weighted.add_edge('Abhishek Bachchan','Akshay Kumar',weight=7)
G_weighted.add_edge('Abhishek Bachchan','Dev Anand', weight=1)
G_weighted.add_edge('Dev Anand','Aaamir Khan',weight=1)
weighted network

上图展示了采用 circular 布局的加权演员网络。边的宽度表示两个节点之间的权重。

多重图

我们可以为边设置不同的属性。例如,可以使用 relation 属性来定义节点 “A” 与 “B” 之间的“邻居”关系。如果在同一网络中,两个节点由两条不同的边(关系)相连,那么我们就得到一个多重图。我们可以使用 MultiGraph 类来构建多重图。

G = nx.MultiGraph()
G.add_edge('A','B',relation ='neighbor')
G.add_edge('A','B',relation='friend)
G.add_edge('B','C', relation='neighbor')
G.add_edge('D','C',relation='friend')

这段代码将构建一个在 A 与 B 之间具有两条边的图。我们可以用 G.edges() 检查连接,输出将显示:

MultiEdgeDataView([('A', 'B', {'relation': 'neighbor'}), ('A', 'B', {'relation': 'friend'}), ('B', 'C', {'relation': 'neighbor'}), ('B', 'D', {'relation': 'neighbor'}), ('C', 'D', {'relation': 'friend'})])

网络连通性

现在网络已经构建完成,我们能否进一步了解网络中某个特定节点的信息?当然可以,让我们来探索一些度量。

度(Degree)

节点的度定义为该节点的连接数。NetworkX 提供了 degree 函数,可用于确定网络中某个节点的度。

nx.degree(G_symmetric, 'Dev Anand`)

这将返回 3,因为 Dev Anand 在该网络中只与三位演员合作过。

聚类系数

人们观察到,在社交网络中共享连接的人往往会形成关联。换句话说,社交网络中具有形成簇的倾向。我们可以确定某个节点的簇特征,即局部聚类系数(Local Clustering Coefficient),它是该节点的好友(即连接)中彼此也相连的对数所占的比例。要计算局部聚类系数,我们使用 nx.clustering(Graph, Node) 函数。

在对称的演员网络中,您会发现Dev Anand 的局部聚类系数为 1,而 Abhishek Bachchan 的局部聚类系数为 0.67。

该对称演员网络的平均聚类系数(所有局部聚类系数之和除以节点数)为 0.867。我们可以使用以下方法获得:

nx.average_clustering(G_symmetric)

距离

我们还可以使用 nx.shortest_path(Graph, Node1, Node2) 和 nx.shortest_path_length(Graph, Node1, Node2) 分别确定两个节点之间的最短路径及其长度。

执行

nx.shortest_path(G_symmetric, 'Dev Anand', 'Akshay Kumar')

返回

['Dev Anand', 'Amitabh Bachchan', 'Akshay Kumar']

我们可以使用广度优先搜索算法,从某个节点开始,找出该节点到网络中其他所有节点的距离。networkX 提供了 bfs_tree 函数来完成此操作。因此,如果您尝试 T = nx.bfs_tree(G_symmetric, 'Dev Anand') 并绘制该树,我们将得到一个网络结构,展示从Dev Anand 出发如何到达网络中的其他节点。

nodes

离心率(Eccentricity)

节点 A 的离心率定义为 A 与所有其他节点之间的最大距离。可以使用 nx.eccentricity() 函数求得。在该对称演员网络中,Dev Anand 的离心率为 2,而 Abhishek Bachchan 的离心率为 1(它与所有人相连)。

网络影响者

上文我们了解了一些网络距离度量,它们有助于判断信息将在网络中如何传播。本节我们将学习如何找出网络中最重要的节点(个体)。这些参数称为中心性度量。

还记得高中里那个很受欢迎的女生,或学校里的棒球队明星吗?他们能左右您的高中体验是天堂还是地狱。是什么让他们拥有这种影响力?中心性度量 能帮助我们识别网络中的受欢迎者、最受喜爱者以及最大的影响者。

度中心性

最受欢迎或更受喜爱的人通常拥有更多朋友。度中心性衡量的是某个节点在网络中的连接数量。它基于“重要节点具有更多连接”的事实。NetworkX 提供了 degree_centrality() 函数来计算网络中所有节点的度中心性。

特征向量中心性

决定一个节点重要性的,不仅仅是其连接了多少人,还在于它连接的人是什么类型。在德里马路上,每当交警抓到有人违反交通规则,交警常听到的第一句话是:“你知道我跟谁有关系吗?”

特征向量中心性衡量的正是这一点。如果一个节点连接着其他重要节点,那么它就被视为重要。我们可以使用 NetworkX 的 eigenvector_centrality() 函数来计算网络中所有节点的特征向量中心性。

Google 的 PageRank 算法是特征向量中心性算法的一种变体。

中介中心性

中介中心性体现的是控制力。它表示某个点出现在连接一对点的测地线(最短路径)上的频率。它量化了某个节点在两其他节点之间被选作最短路径的次数。中介中心性较高的节点在网络的通信/信息流中扮演重要角色。具有高中介中心性的节点可以对他人施加战略性控制与影响。处于这种战略位置的个体可以通过扣留信息或在传递过程中“染色”,来影响整个群体。

Networkx 提供了 betweenness_centrality() 函数来衡量网络的中介中心性。它可以选择是否对中介值进行归一化、是否在中心性计算中包含权重,以及是否在最短路径计数中包含端点。

综合实战

让我们从 Facebook 数据开始。本次分析将使用 Facebook 组合自我网络数据集,它包含十位个体的 Facebook 好友列表聚合得到的网络。您可以从斯坦福大学网站下载所需的 facebook_combined.txt 文件。

您也可以通过 Facebook/Twitter 的 API 获取您自己的 Facebook/Twitter 数据。敬请期待接下来的教程,我们将学习如何使用 Facebook 和 Twitter 的 API 获取数据,并利用这里学到的方法进行分析。

我们读取文件并构建图:

G_fb = nx.read_edgelist("facebook_combined.txt", create_using = nx.Graph(), nodetype=int)

该网络由 4,039 个节点构成,通过 88,234 条边相连!没错,这是个大网络。您可以使用 info() 函数获取信息。

[In]: print(nx.info(G_fb))


[Out]: Name:
       Type: Graph
       Number of nodes: 4039
       Number of edges: 88234
       Average degree:  43.6910

下图展示了该网络:

network

我们还可以按度(Degree) 调整节点颜色、按中介中心性(Betweenness Centrality) 调整节点大小进行可视化。代码如下:

pos = nx.spring_layout(G_fb)
betCent = nx.betweenness_centrality(G_fb, normalized=True, endpoints=True)
node_color = [20000.0 * G_fb.degree(v) for v in G_fb]
node_size =  [v * 10000 for v in betCent.values()]
plt.figure(figsize=(20,20))
nx.draw_networkx(G_fb, pos=pos, with_labels=False,
                 node_color=node_color,
                 node_size=node_size )
plt.axis('off')

得到的图如下所示:

resulting graph

您还可以使用以下方法获取具有最高中介中心性的节点标签:

sorted(betCent, key=betCent.get, reverse=True)[:5]

下表列出了中心性度量最高的五个节点标签。

度中心性 特征向量中心性 中介中心性
107 1912 107
1684 2266 1684
1912 2206 3437
3437 2233 1912
0 2464 1085

我们可以看到,度中心性(度的度量)与中介中心性(信息流控制)之间有一些共同的节点。更连接广泛的节点自然更可能位于其他节点之间的最短路径上。节点 1912 很重要,因为在我们考虑的三种中心性度量中它都至关重要。

参考资料

  • 演员数据来自 IMDB 网站
  • 了解 NetworkX 及其函数的最佳途径是其文档

如果您想进一步学习用 Python 进行社会网络分析,请参加 DataCamp 的课程 Analyzing Social Media Data in Python。

主题
Python
数据分析

进一步了解 Python 与数据分析

课程

在 Python 中分析社交媒体数据

4 小时
24.4K
在本课程中,你将学习如何收集 Twitter 数据并分析 Twitter 文本、网络和地理来源。
查看详情开始课程

创建您的免费账户

实践并学习路径你的进步。

使用 Google 继续
继续操作即表示您接受我们的《使用条款》和《隐私政策》,并同意您的数据存储在美国。
查看更多