Áp phích đầu tiên ở đây, vì vậy hãy nhẹ nhàng. :)Đặt hình dạng nút động trong mạng với matplotlib
Tôi đang cố gắng để vẽ đồ thị một mạng lưới các nhân vật của các loại khác nhau trong Networkx và muốn thiết lập hình dạng nút khác nhau đối với từng loại. Ví dụ, tôi muốn nhân vật là vòng tròn, sinh vật là hình tam giác, v.v. Tôi đã cố gắng tìm ra điều này trong vài giờ và đã tìm kiếm SO rộng rãi, nhưng tôi đã không tìm thấy cách để đạt được điều này khác hơn là đặt các node_lists khác nhau cho từng loại ký tự và hiển thị chúng một cách riêng biệt, điều này dường như không trực quan.
Vấn đề là tôi không thể truy cập vào các giá trị điển node_shape từ bên trong:
nx.draw_networkx_nodes(G, pos)
Tôi đã thử nhiều giải pháp trong đó có cố gắng truy cập các thuộc tính nút, tạo ra một từ điển bên ngoài hoặc danh sách và truy cập nó từ bên trong cuộc gọi, thiết lập một danh sách hiểu hoặc lặp và không có gì có vẻ làm việc.
Hoặc tôi chuyển danh sách được kéo vào bán buôn, từ điển, chức năng không thể băm, hoặc thể hiện của danh sách như shape_list.pop(0)
, trong trường hợp đó, hàm chỉ lấy giá trị đầu tiên và áp dụng nó cho tất cả các nút.
Tôi có thể đặt màu bằng cách tạo danh sách node_colors riêng biệt được lặp lại bởi hàm và thậm chí đã thử tạo từ điển để node_shape được kích hoạt bởi node_color, nhưng điều đó cũng không hoạt động.
Tôi đang hy vọng sẽ sử dụng mã như là một add-on cho một ứng dụng web phát triển bằng Python 3.4 và Django 1,8, vì vậy Graphviz không phải là một lựa chọn.
Cảm ơn bạn trước vì đã hỗ trợ hoặc tham khảo các thư viện thay thế.
Đây là mã của tôi:
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()
một số lỗi thụt lề của bạn có lỗi. Bạn có thể lấy những gì bạn đã đăng và đảm bảo rằng sao chép/dán tạo ra mã khả thi? – Joel
Vì vậy, câu trả lời cơ bản (như tôi nhớ lại) là mỗi lệnh vẽ đồ thị phải sử dụng cùng một hình dạng cho mỗi nút. Vì vậy, nếu bạn muốn vẽ nhiều hình dạng khác nhau, bạn sẽ cần phải gọi 'draw_networkx_nodes' mỗi lần. Nó sử dụng 'matplotlib.pyplot.scatter', (http://matplotlib.org/api/pyplot_api.html # matplotlib.pyplot.scatter) đó là lý do tại sao nó có hạn chế này. – Joel
Tôi đã cập nhật mã. Cảm ơn, Joel. Có một thư viện khác làm việc với Python3 có thể làm điều này không? – ToferC