0

我正在尝试学习网络分析,所以我在网上使用希拉里克林顿的电子邮件来查看谁给谁发了电子邮件。

我的数据在一个名为 hrc_dict 的字典中。我有一个发送者和接收者的元组,然后是电子邮件的频率。这是字典的一部分:

{('Hillary Clinton', 'Cheryl Mills'): 354, ('Hillary Clinton', 'l'): 1, ('Linda Dewan', 'Hillary Clinton'): 1, ('Hillary Clinton', 'Capricia Marshall'):9,('Phillip Crowley','Hillary Clinton'):2,('Cheryl Mills','Anne-Marie Slaughter'):1}

我在 Jupyter 中使用 Networkx 创建图表。我的代码如下:

import networkx as nx
import matplotlib.pyplot as plt

G = nx.Graph()

G.add_nodes_from(hrc_dict)

for s, r in hrc_dict:
    G.add_edge((s,r), hrc_dict[(s,r)])

G.add_edge((s,r), hrc_dict[(s,r)])

当我调用 nx.Graph() 时,什么都没有打印出来,当我调用 G.nodes() 时,并不是所有的节点都显示出来。我在这里粘贴了一些输出:

[1, 2, 3, 4, 5, 6, 7, 8, 'Mark Penn', 10, ('Todd Stern', 'Hillary Clinton'), 12,]

当我调用 G.edges() 时,我得到以下内容,这似乎是正确的

[(1, ('Hillary Clinton', 'l')), (1, ('Linda Dewan', 'Hillary Clinton')), (1, ('Hillary Clinton', 'Thomas Shannon')), (1 , ('Cheryl Mills', 'Anne-Marie Slaughter'), (1, ('Christopher Butzgy', 'Hillary Clinton'))]

有谁知道如何将节点正确添加到我的图表中。我假设每个人都需要成为一个节点,那么如何分解元组并分别添加名称?边缘是否正确显示或者我需要以不同的方式输入它们?

4

2 回答 2

3

要将每个人添加为节点,您还需要更改add_nodes_from.

像这样的东西:

srcs, dests = zip(* [(fr, to) for (fr, to) in hrc_dict.keys()])
G.add_nodes_from(srcs+dests)

现在意味着来自的节点列表G.nodes()将是:

['Cheryl Mills',
 'Capricia Marshall',
 'Anne-Marie Slaughter',
 'Phillip Crowley',
 'Hillary Clinton',
 'l',
 'Linda Dewan']

(您不会得到任何重复,因为 networkx 将图形存储为字典)。

注意:如果您使用下面的方法添加边,则无需先添加节点 - 但如果您的节点可能没有邻居(或仅节点的另一个原因)重要),此代码将执行此操作。

然后基本上按照乔尔的回答添加边缘;还要注意属性“weight”的使用,所以布局可以直接利用信息。

import networkx as nx
import matplotlib.pyplot as plt

hrc_dict = {('Hillary Clinton', 'Cheryl Mills'): 355, ('Hillary Clinton', 'l'): 1, ('Linda Dewan', 'Hillary Clinton'): 1, ('Hillary Clinton', 'Capricia Marshall'): 9, ('Phillip Crowley', 'Hillary Clinton'): 2, ('Cheryl Mills', 'Anne-Marie Slaughter'): 1}

G = nx.Graph()

# To add the a node for each of the email parties:
srcs, dests = zip(* [(fr, to) for (fr, to) in hrc_dict.keys()])
G.add_nodes_from(srcs + dests)
# (but it isn't needed IF the following method is used
#  to add the edges, since add_edge also creates the nodes if
#  they don't yet exist)

# note the use of the attribute "weight" here
for (s,r), count in hrc_dict.items():
    G.add_edge(s, r, weight=count)

# produce info to draw:
# a) if weight was used above, spring_layout takes 
#    into account the edge strengths
pos = nx.spring_layout(G)

# b) specifiy edge labels explicitly
# method from https://groups.google.com/forum/#!topic/networkx-discuss/hw3OVBF8orc
edge_labels=dict([((u,v,),d['weight'])
             for u,v,d in G.edges(data=True)])

# draw it
plt.figure(1);
nx.draw_networkx(G, pos, with_labels=True)
nx.draw_networkx_edge_labels(G,pos,edge_labels=edge_labels)

plt.axis('equal') # spring weighting makes more sense this way
plt.show()

这就是我们可能会看到的:

示例输出 - 请注意,由于 HC/A-MS 边缘非常强,因此非常短

于 2015-12-08T20:22:36.467 回答
0

您的问题基本上出在这一点:

G.add_edge((s,r), hrc_dict[(s,r)])

networkx 将此解释为“在第一个参数(s,r)和第二个参数之间添加一条边hrc_dict[(s,r)]”。因此,例如('Hillary Clinton', 'Cheryl Mills'): 354成为 node('Hillary Clinton', 'Cheryl Mills')和 node之间的一条边354。而是尝试

G.add_edge(s, r, count = hrc_dict[(s,r)])
于 2015-12-08T07:02:50.537 回答