第一次在這裏發佈海報,所以請溫柔。 :)用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