Matplotlib 使用networkx绘制三个人的普通朋友连接

Matplotlib 使用networkx绘制三个人的普通朋友连接,matplotlib,python-3.5,networkx,Matplotlib,Python 3.5,Networkx,我有三个人(可以选择添加更多的人),我想将每个人的朋友列表显示为一个圆圈。每人一圈。接下来,如果两个人有相同的朋友,我想添加边(连接) Mike_friends = ['Al', 'Niki', 'Silvia', 'Anna', 'Matt', 'Gia', 'Nick', 'Maud', 'Sarah', 'Lisa', 'Kelvin'] Alex_friends = ['Harvey', 'Steve', 'Michael', 'Maud', 'Al', 'Kam', 'Hank'] S

我有三个人(可以选择添加更多的人),我想将每个人的朋友列表显示为一个圆圈。每人一圈。接下来,如果两个人有相同的朋友,我想添加边(连接)

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个带连接的圆圈没有出现。谢谢你的帮助。删除了“返回G”

这里有一种方法。首先,你会发现迈克、亚历克斯和斯蒂芬是多少普通朋友。我使用
set
;这是迈克和亚历克斯的例子

M_A_common = len(set(Mike_friends) & set(Alex_friends))
我的图表中的节点称为
Mike
Alex
Stephen
。我在下面设置了edge
Mike--Alex
,因此它的值为
M_A_common

G.add_edge('Mike', 'Alex', common_friends=M_A_common)
下面是所有朋友的完整示例,我用
nx.draw
绘制网络,用
nx.draw\u networkx\u edge\u标签绘制边缘标签

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
。要绘制多条边,请查看

编辑:

要为上述代码添加自定义节点标签(例如节点名称+好友总数),您可以使用
nx。绘制\u networkx\u标签
,如下所示:

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
的字典中

要获得所有可能的边,我使用

输出:

编辑2:


我更正了代码中的一行,该行现在提供了不同的边缘标签(仅值不带
边缘标签的键)。

@Bonlenfum您在我之前的networkx问题中提供了帮助,对我如何绘制社交朋友连接有何建议?您需要真正备份并再次访问。代码中的误会太多了。@Joel感谢您的评论。我调用了这个函数。N1、N2、N3中的i代表列表中的每个项目。”现在将在所有迭代之后调用returng。我从add.edge编辑到add.edges\u。同样的问题也存在,只是没有圆的空正方形。还有一个问题是
G
发生了什么。它目前是一个全局变量。您的函数也在返回
G
,但返回的值不会发送到任何地方。@Joel更好吗?非常感谢@edo有办法显示每个节点的好友总数吗?我可以用同样的方法为10-20个朋友创建这个社交圈,对吗?我有一个无关的问题:有没有一种快速的方法来显示节点Mike和Alex之间的两个普通朋友的名字?你可以设置一个边缘属性,将普通朋友的名字保存在一个字符串中,例如,
,'。join(list(set(friends[node_1])和set(friends[node_2]))
,这就画出了这个新的边缘标签。非常感谢,它很好用。最后,如果我使用20、50或100个节点的网络,而不是这里的3个节点,您还会使用这个networkx库吗?或者,对于更多具有高维数据的节点,是否有更好的可视化效果?Networkx适合处理数据,但如果您有很多节点,则值得研究其他图形可视化解决方案。我只使用了networkx,所以我没有任何可供推荐的替代工具。
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()