使用 networkx 绘制三个人的共同朋友关系
Draw common friends connections of three people using networkx
我有三个人(可以选择添加更多人),我想将每个人的朋友列表显示为一个圈子。所以,每人 1 个圆圈。接下来,如果两个人有相同的朋友,我想添加边(连接)。
Mike_friends = ['Al', 'Niki', 'Silvia', 'Anna', 'Matt', 'Gia', 'Nick', 'Maud', 'Sarah', 'Lisa', 'Kelvin']
Alex_friends = ['Harvey', 'Steve', 'Michael', 'Maud', 'Al', 'Kam', 'Hank']
Stephen_friends = ['Lisa','Rosie','Mango','Kate','Nate','Maud','Kelvin','Elvis','Arstad','Jesus','Johan','Jay','Gia','Niki','Harvey','Paul','Mike','Alex','Anna']
import networkx as nx
import matplotlib.pyplot as plt
def link_networks(N1, N2, N3, N4=None, N5=None, N6=None, N7=None, N8=None, N9=None):
G = nx.Graph()
for item1 in N1:
for item2 in N2:
for item3 in N3:
if item1 in N1 == item2 in N2:
G.add_edge(item1, item2)
elif item1 in N1 == item3 in N3:
G.add_edge(item1, item3)
elif item2 in N2 == item3 in N3:
G.add_edge(item2, item3)
link_networks(Mike_friends, Alex_friends, Stephen_friends)
plt.figure(figsize = (20, 10))
mytitle = "friend circle connections"
plt.title(mytitle, fontsize=40)
nx.draw_networkx(G, font_size=10, node_size=2000, alpha=0.6)
plt.savefig("friend_circles.pdf")
问题:我得到空图,没有显示 3 个有连接的圆圈。感谢帮助。已删除 'Return G'。
这是一种方法。首先,您会发现 有多少 个共同朋友有 Mike、Alex 和 Stephen。我通过使用 set
来做到这一点;这是迈克和亚历克斯的例子。
M_A_common = len(set(Mike_friends) & set(Alex_friends))
我图中的节点称为 Mike
、Alex
和 Stephen
。下面我设置边 Mike -- Alex
所以它的值为 M_A_common
.
G.add_edge('Mike', 'Alex', common_friends=M_A_common)
这是所有朋友的完整示例,我用 nx.draw
绘制网络,用 nx.draw_networkx_edge_labels
绘制边缘标签。
import networkx as nx
import matplotlib.pyplot as plt
Mike_friends = ['Al', 'Niki', 'Silvia', 'Anna', 'Matt', 'Gia', 'Nick', 'Maud', 'Sarah', 'Lisa', 'Kelvin']
Alex_friends = ['Harvey', 'Steve', 'Michael', 'Maud', 'Al', 'Kam', 'Hank']
Stephen_friends = ['Lisa','Rosie','Mango','Kate','Nate','Maud','Kelvin','Elvis','Arstad','Jesus','Johan','Jay','Gia','Niki','Harvey','Paul','Mike','Alex','Anna']
G = nx.Graph()
G.add_node('Mike')
G.add_node('Alex')
G.add_node('Stephen')
M_A_common = len(set(Mike_friends) & set(Alex_friends)) # number of common friends
M_S_common = len(set(Mike_friends) & set(Stephen_friends)) # number of common friends
S_A_common = len(set(Stephen_friends) & set(Alex_friends)) # number of common friends
G.add_edge('Mike', 'Alex', common_friends=M_A_common)
G.add_edge('Mike', 'Stephen', common_friends=M_S_common)
G.add_edge('Stephen', 'Alex', common_friends=S_A_common)
pos = nx.circular_layout(G)
nx.draw(G, pos, node_size=2000, with_labels=True)
edge_labels = nx.get_edge_attributes(G, 'common_friends')
nx.draw_networkx_edge_labels(G, pos, labels=edge_labels)
plt.show()
您可以不写共同朋友的数量,例如显示边厚的普通朋友数量。
当然,朋友越多,组合就越多,所以您可能希望自动计算普通朋友。
另外,如果你想为每个共同的朋友设置多个边,你需要使用 MultiGraph
而不是 Graph
。要绘制多条边,请查看 here.
编辑:
要为上面的代码添加自定义节点标签(例如节点名称 + 好友总数),您可以像这样使用 nx.draw_networkx_labels
:
pos = nx.circular_layout(G)
nx.draw(G, pos, node_size=2000, with_labels=False)
node_labels = {
'Mike': 'Mike (' + str(len(Mike_friends)) + ' total)',
'Alex': 'Alex (' + str(len(Alex_friends)) + ' total)',
'Stephen': 'Stephen (' + str(len(Stephen_friends)) + ' total)'
}
nx.draw_networkx_labels(G, pos, labels=node_labels)
edge_labels = nx.get_edge_attributes(G, 'common_friends')
nx.draw_networkx_edge_labels(G, pos, labels=edge_labels)
plt.show()
如果你有 20 个朋友,上面的代码会变得非常混乱。下面是一种更优雅的方法,我将节点及其朋友存储在名为 friends
.
的字典中
为了获得所有可能的边,我使用 itertools.combinations
import networkx as nx
import matplotlib.pyplot as plt
from itertools import combinations
G = nx.Graph()
friends = {
'Mike': ['Al', 'Niki', 'Silvia', 'Anna', 'Matt', 'Gia', 'Nick', 'Maud', 'Sarah', 'Lisa', 'Kelvin'],
'Alex': ['Harvey', 'Steve', 'Michael', 'Maud', 'Al', 'Kam', 'Hank'],
'Stephen': ['Lisa','Rosie','Mango','Kate','Nate','Maud','Kelvin','Elvis','Arstad','Jesus','Johan','Jay','Gia','Niki','Harvey','Paul','Mike','Alex','Anna']
}
persons = list(friends.keys()) # Mike, Alex, Stephen
G.add_nodes_from(persons)
combos = list(combinations(persons, 2)) # all 2-combinations of `persons`
for edge in combos:
node_1, node_2 = edge[0], edge[1]
common = len(set(friends[node_1]) & set(friends[node_2])) # number of common friends
G.add_edge(node_1, node_2, common_friends=common)
node_labels = {person: person + ' (' + str(len(friends[person])) + ' total)' for person in persons}
edge_labels = nx.get_edge_attributes(G, 'common_friends')
pos = nx.circular_layout(G)
nx.draw(G, pos, node_size=2000, with_labels=False)
nx.draw_networkx_labels(G, pos, labels=node_labels)
nx.draw_networkx_edge_labels(G, pos, edge_labels=edge_labels)
plt.show()
输出:
编辑 2:
我更正了代码中的一行,该行现在提供了不同的边缘标签(只有 edge_labels
没有键的值)。
我有三个人(可以选择添加更多人),我想将每个人的朋友列表显示为一个圈子。所以,每人 1 个圆圈。接下来,如果两个人有相同的朋友,我想添加边(连接)。
Mike_friends = ['Al', 'Niki', 'Silvia', 'Anna', 'Matt', 'Gia', 'Nick', 'Maud', 'Sarah', 'Lisa', 'Kelvin']
Alex_friends = ['Harvey', 'Steve', 'Michael', 'Maud', 'Al', 'Kam', 'Hank']
Stephen_friends = ['Lisa','Rosie','Mango','Kate','Nate','Maud','Kelvin','Elvis','Arstad','Jesus','Johan','Jay','Gia','Niki','Harvey','Paul','Mike','Alex','Anna']
import networkx as nx
import matplotlib.pyplot as plt
def link_networks(N1, N2, N3, N4=None, N5=None, N6=None, N7=None, N8=None, N9=None):
G = nx.Graph()
for item1 in N1:
for item2 in N2:
for item3 in N3:
if item1 in N1 == item2 in N2:
G.add_edge(item1, item2)
elif item1 in N1 == item3 in N3:
G.add_edge(item1, item3)
elif item2 in N2 == item3 in N3:
G.add_edge(item2, item3)
link_networks(Mike_friends, Alex_friends, Stephen_friends)
plt.figure(figsize = (20, 10))
mytitle = "friend circle connections"
plt.title(mytitle, fontsize=40)
nx.draw_networkx(G, font_size=10, node_size=2000, alpha=0.6)
plt.savefig("friend_circles.pdf")
问题:我得到空图,没有显示 3 个有连接的圆圈。感谢帮助。已删除 'Return G'。
这是一种方法。首先,您会发现 有多少 个共同朋友有 Mike、Alex 和 Stephen。我通过使用 set
来做到这一点;这是迈克和亚历克斯的例子。
M_A_common = len(set(Mike_friends) & set(Alex_friends))
我图中的节点称为 Mike
、Alex
和 Stephen
。下面我设置边 Mike -- Alex
所以它的值为 M_A_common
.
G.add_edge('Mike', 'Alex', common_friends=M_A_common)
这是所有朋友的完整示例,我用 nx.draw
绘制网络,用 nx.draw_networkx_edge_labels
绘制边缘标签。
import networkx as nx
import matplotlib.pyplot as plt
Mike_friends = ['Al', 'Niki', 'Silvia', 'Anna', 'Matt', 'Gia', 'Nick', 'Maud', 'Sarah', 'Lisa', 'Kelvin']
Alex_friends = ['Harvey', 'Steve', 'Michael', 'Maud', 'Al', 'Kam', 'Hank']
Stephen_friends = ['Lisa','Rosie','Mango','Kate','Nate','Maud','Kelvin','Elvis','Arstad','Jesus','Johan','Jay','Gia','Niki','Harvey','Paul','Mike','Alex','Anna']
G = nx.Graph()
G.add_node('Mike')
G.add_node('Alex')
G.add_node('Stephen')
M_A_common = len(set(Mike_friends) & set(Alex_friends)) # number of common friends
M_S_common = len(set(Mike_friends) & set(Stephen_friends)) # number of common friends
S_A_common = len(set(Stephen_friends) & set(Alex_friends)) # number of common friends
G.add_edge('Mike', 'Alex', common_friends=M_A_common)
G.add_edge('Mike', 'Stephen', common_friends=M_S_common)
G.add_edge('Stephen', 'Alex', common_friends=S_A_common)
pos = nx.circular_layout(G)
nx.draw(G, pos, node_size=2000, with_labels=True)
edge_labels = nx.get_edge_attributes(G, 'common_friends')
nx.draw_networkx_edge_labels(G, pos, labels=edge_labels)
plt.show()
您可以不写共同朋友的数量,例如显示边厚的普通朋友数量。
当然,朋友越多,组合就越多,所以您可能希望自动计算普通朋友。
另外,如果你想为每个共同的朋友设置多个边,你需要使用 MultiGraph
而不是 Graph
。要绘制多条边,请查看 here.
编辑:
要为上面的代码添加自定义节点标签(例如节点名称 + 好友总数),您可以像这样使用 nx.draw_networkx_labels
:
pos = nx.circular_layout(G)
nx.draw(G, pos, node_size=2000, with_labels=False)
node_labels = {
'Mike': 'Mike (' + str(len(Mike_friends)) + ' total)',
'Alex': 'Alex (' + str(len(Alex_friends)) + ' total)',
'Stephen': 'Stephen (' + str(len(Stephen_friends)) + ' total)'
}
nx.draw_networkx_labels(G, pos, labels=node_labels)
edge_labels = nx.get_edge_attributes(G, 'common_friends')
nx.draw_networkx_edge_labels(G, pos, labels=edge_labels)
plt.show()
如果你有 20 个朋友,上面的代码会变得非常混乱。下面是一种更优雅的方法,我将节点及其朋友存储在名为 friends
.
为了获得所有可能的边,我使用 itertools.combinations
import networkx as nx
import matplotlib.pyplot as plt
from itertools import combinations
G = nx.Graph()
friends = {
'Mike': ['Al', 'Niki', 'Silvia', 'Anna', 'Matt', 'Gia', 'Nick', 'Maud', 'Sarah', 'Lisa', 'Kelvin'],
'Alex': ['Harvey', 'Steve', 'Michael', 'Maud', 'Al', 'Kam', 'Hank'],
'Stephen': ['Lisa','Rosie','Mango','Kate','Nate','Maud','Kelvin','Elvis','Arstad','Jesus','Johan','Jay','Gia','Niki','Harvey','Paul','Mike','Alex','Anna']
}
persons = list(friends.keys()) # Mike, Alex, Stephen
G.add_nodes_from(persons)
combos = list(combinations(persons, 2)) # all 2-combinations of `persons`
for edge in combos:
node_1, node_2 = edge[0], edge[1]
common = len(set(friends[node_1]) & set(friends[node_2])) # number of common friends
G.add_edge(node_1, node_2, common_friends=common)
node_labels = {person: person + ' (' + str(len(friends[person])) + ' total)' for person in persons}
edge_labels = nx.get_edge_attributes(G, 'common_friends')
pos = nx.circular_layout(G)
nx.draw(G, pos, node_size=2000, with_labels=False)
nx.draw_networkx_labels(G, pos, labels=node_labels)
nx.draw_networkx_edge_labels(G, pos, edge_labels=edge_labels)
plt.show()
输出:
编辑 2:
我更正了代码中的一行,该行现在提供了不同的边缘标签(只有 edge_labels
没有键的值)。