First time poster here, so please be gentle. :)
I'm trying to graph a network of characters of different types in Networkx and want to set different node shapes for each type. For example, I'd like characters to be circles, creatures to be triangles, etc. I've tried to figure this out for several hours and have searched SO extensively, but I haven't found a way to achieve this other than to set different node_lists for each type of character and render them separately, which just seems counterintuitive.
The issue is that I'm unable to access the node_shape dictionary value from within:
nx.draw_networkx_nodes(G, pos)
I've tried multiple solutions including trying to access the node attribute, creating an external dictionary or list and accessing it from within the call, setting up a list comprehension or iterator and nothing seems to work.
Either I pass a list, which is pulled in wholesale, a dictionary, which the function isn't able to hash, or an instance of the list such as shape_list.pop(0)
, in which case the function only takes the first value and applies it to all nodes.
I am able to set color by creating a separate node_colors list which is iterated over by the function and even tried creating a dictionary so that the node_shape is triggered by node_color, but that didn't work either.
I'm hoping to use the code as an add-on to a web app developed in Python 3.4 and Django 1.8, so Graphviz isn't an option.
Thanks in advance for any assistance or reference to alternate libraries.
Here is my code:
import json
import requests
import networkx as nx
import matplotlib.pyplot as pltpersonas = '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'] = namestory_objects[name]['story'] = storystory_objects[name]['c_type'] = c_typestory_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()