Locandina prima volta qui, quindi si prega di essere gentile. :)Imposta la forma del nodo dinamico nella rete con matplotlib
Sto provando a rappresentare graficamente una rete di caratteri di tipi diversi in Networkx e voglio impostare forme di nodo diverse per ogni tipo. Ad esempio, mi piacerebbe che i personaggi fossero cerchi, che le creature fossero triangoli, ecc. Ho cercato di capirlo per diverse ore e ho cercato in modo approfondito, ma non ho trovato un modo per ottenere questo oltre a imposta diverse node_list per ciascun tipo di carattere e renderle separatamente, il che sembra poco intuitivo.
Il problema è che sono in grado di accedere al valore dizionario node_shape dall'interno:
nx.draw_networkx_nodes(G, pos)
Ho provato diverse soluzioni, tra cui il tentativo di accedere all'attributo nodo, la creazione di un dizionario o una lista esterna e l'accesso dall'interno della chiamata, impostando una list comprehension o iterator e niente sembra funzionare.
O si passa una lista, che viene inserita all'ingrosso, un dizionario, che la funzione non è in grado di hash, o un'istanza della lista come shape_list.pop(0)
, nel qual caso la funzione prende solo il primo valore e lo applica a tutti i nodi.
Sono in grado di impostare il colore creando un elenco node_colors separato che viene iterato dalla funzione e anche provato a creare un dizionario in modo che node_shape sia attivato da node_color, ma non ha funzionato neanche.
Spero di utilizzare il codice come componente aggiuntivo di un'app Web sviluppata in Python 3.4 e Django 1.8, quindi Graphviz non è un'opzione.
Grazie in anticipo per qualsiasi assistenza o riferimento a biblioteche alternative.
Ecco il mio codice:
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()
alcuni dei vostri rientri hanno errori. Puoi prendere ciò che hai postato e assicurarti che copia/incolla produca codice lavorabile? – Joel
Quindi, la risposta di base (come ricordo) è che ogni comando di plottaggio deve usare la stessa forma per ogni nodo. Quindi, se vuoi tracciare più forme diverse, dovrai chiamare 'draw_networkx_nodes' ogni volta. Usa 'matplotlib.pyplot.scatter', (http://matplotlib.org/api/pyplot_api.html # matplotlib.pyplot.scatter) ed è per questo che ha questa restrizione. – Joel
Ho aggiornato il codice. Grazie, Joel. C'è un'altra libreria che funziona con Python3 che potrebbe fare questo? – ToferC