如何在 Networkx 中将节点和边添加到网络分析图中?

How to add nodes and edges to a network analysis graph in Networkx?

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

我的数据在名为 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’))]

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

你的问题基本出在这一点:

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

networkx 将其解释为 "add an edge between the first argument (s,r) and the second argument hrc_dict[(s,r)]." 因此,例如 ('Hillary Clinton', 'Cheryl Mills'): 354 成为节点 ('Hillary Clinton', 'Cheryl Mills') 和节点 354 之间的边。而是尝试

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

要将每个人添加为一个节点,还需要更改使用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()

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