第一次在这里发布海报,所以请温柔。 :)用matplotlib在网络中设置动态节点形状
我试图在Networkx中绘制不同类型字符的网络,并且想要为每种类型设置不同的节点形状。例如,我希望角色是圆形,生物是三角形等。我试图找出这个问题几个小时,并且已经广泛搜索过,但是我还没有找到一种方法来实现这一点,而不是为每种类型的角色设置不同的node_lists并单独渲染它们,这似乎是违反直觉的。
的问题是,我无法从访问node_shape字典值内:
nx.draw_networkx_nodes(G, pos)
我试过多种解决方案,包括试图访问节点的属性,创建一个外部字典或列表和访问它在调用中,建立一个列表理解或迭代器,似乎没有任何工作。
要么我传递一个列表,它是批量拉取的,字典,函数不能散列的字典,或者列表的一个实例,例如shape_list.pop(0)
,在这种情况下函数只取第一个值,而将其应用于所有节点。
我可以通过创建一个单独的node_colors列表来设置颜色,该列表由函数迭代,甚至尝试创建一个字典,以便node_shape由node_color触发,但这也不起作用。
我希望将代码作为Python 3.4和Django 1.8开发的Web应用程序的附加组件使用,因此Graphviz不是一个选项。
预先感谢您提供任何帮助或参考替代图书馆。
这里是我的代码:
import json
import requests
import networkx as nx
import matplotlib.pyplot as plt
personas = 'http://story-chronicles.herokuapp.com/storyobjects/'
target = requests.get(personas)
x = target.json()
story_objects = {}
labels = {}
node_colors = []
for character in x:
name = character["name"]
story = character["story"]
c_type = character["c_type"]
story_objects[name] = {}
story_objects[name]['name'] = name
story_objects[name]['story'] = story
story_objects[name]['c_type'] = c_type
story_objects[name]['to_relationships'] = []
if character['c_type'] == "Character":
story_objects[name]['node_shape'] = 'o'
story_objects[name]['node_color'] = 'r'
elif character['c_type'] == "Organization":
story_objects[name]['node_shape'] = 'h'
story_objects[name]['node_color'] = 'b'
elif character['c_type'] == "Creature":
story_objects[name]['node_shape'] = '^'
story_objects[name]['node_color'] = 'g'
elif character['c_type'] == "Force":
story_objects[name]['node_shape'] = 'v'
story_objects[name]['node_color'] = 'c'
elif character['c_type'] == "Thing":
story_objects[name]['node_shape'] = 's'
story_objects[name]['node_color'] = 'y'
for relationship in character["to_relationships"]:
break_1 = relationship.find(">>")
break_2 = relationship.find("weight:")
sub_1 = relationship[0:break_1].strip()
context = relationship[break_1:break_2]
weight = relationship[break_2+8:-1]
story_objects[name]['to_relationships'].append([sub_1, context, weight])
G=nx.MultiDiGraph()
for sub in story_objects:
s = story_objects[sub]
if s['story'] == "http://story-chronicles.herokuapp.com/story/1/":
G.add_node(s['name'], node_shape=s['node_shape'])
labels[s['name']] = s['name']
node_colors.append(s['node_color'])
print("***", s['name'], "***", s['c_type'])
print("details:", s['node_color'], s['node_shape'])
for i in s['to_relationships']:
print('target:', i[0])
print('context:', i[1])
print('weight:', i[2])
G.add_edge(s['name'], i[0], weight=int(i[2]))
print("")
node_shapes=nx.get_node_attributes(G, 'node_shape') # Latest attempt at getting this to work
node_shapes = [v for k,v in node_shapes.items()]
pos=nx.spring_layout(G)
G.degree(weight=weight)
nx.draw_networkx_nodes(G, pos, node_color=node_colors, node_shape=node_shapes.pop(0)) # <--- This is where I'm having problems
nx.draw_networkx_edges(G, pos)
nx.draw_networkx_labels(G, pos, labels)
plt.show()
您的一些缩进有错误。你可以采取你发布的内容,并确保复制/粘贴产生可行的代码? – Joel
所以 - 基本答案(我记得)是每个绘图命令必须为每个节点使用相同的形状。所以如果你想绘制多个不同的形状,你需要每次调用'draw_networkx_nodes'。它使用'matplotlib.pyplot.scatter',(http://matplotlib.org/api/pyplot_api。html#matplotlib.pyplot.scatter)这就是为什么它有这个限制。 – Joel
我更新了代码。谢谢,乔尔。是否有另一个与Python3一起工作的库可以做到这一点? – ToferC