I am using NetworkX to analyze and visualize social networks. Often, the nodes within the network have attribute information associated with them, such as division. However, I do not always know how many options there might be for the attribute division. For example, sometimes there might be only 3 divisions represented as node attributes within the network, other times there might be 30 divisions.
I've figured out how to set node colors based on node attributes (see code below). However, in this example, I knew how different options there were for the node attribute group (5 options), and set each color automatically.
When there are only 3 or 5 options for node attributes, it's not difficult to pick the node attribute colors, but this becomes unrealistic when there are many more options.
What I would like to figure out is how can I automatically pick the optimal node attribute colors based on the number of node attribute options provided.
Sometime I have have 5 options for the attribute to color by, other times I might have 30 options for the node attribute to color by, and I don't want to set each node color individually.
I'm not sure if this is something that I should be able to do with the colormap
function, or if that is only for color nodes by numeric measures such as degree centrality.
NETWORKX CODE
import networkx as nx
pylab inline
# create an empty graph
g = nx.Graph()
# open csv edgelist and read edges into graph
for line in open('phils_network_edgelist.csv', 'rb'):
edge = line.rstrip().split(',')
g.add_edge(edge[0], edge[1])
# draw network without node color
nx.draw(g, with_labels=False, node_size=25)
# read in node attributes as list of tuples
group_attr = []
for line in open('phils_network_attribute_group.csv', 'rb'):
group_attr.append(tuple(line.rstrip().split(',')))
# convert list of tuples into a dict
group_attr_dict = dict(set(sorted(group_attr)))
# set nodes attributes
nx.set_node_attributes(g, "group", group_attr_dict)
# create empty list for node colors
node_color = []
# for each node in the graph
for node in g.nodes(data=True):
# if the node has the attribute group1
if 'group1' in node[1]['group']:
node_color.append('blue')
# if the node has the attribute group1
elif 'group2' in node[1]['group']:
node_color.append('red')
# if the node has the attribute group1
elif 'group3' in node[1]['group']:
node_color.append('green')
# if the node has the attribute group1
elif 'group4' in node[1]['group']:
node_color.append('yellow')
# if the node has the attribute group1
elif 'group5' in node[1]['group']:
node_color.append('orange')
# draw graph with node attribute color
nx.draw(g, with_labels=False, node_size=25, node_color=node_color)
NETWORK DATA
In[58]:
g.nodes(data=True)
Out[58]:
[('BD', {'group': 'group5'}),
('WC', {'group': 'group3'}),
('BA', {'group': 'group4'}),
('WM', {'group': 'group3'}),
('JR', {'group': 'group1'}),
('JS', {'group': 'group3'}),
('JL', {'group': 'group4'}),
('JM', {'group': 'group2'}),
('JK', {'group': 'group2'}),
('JF', {'group': 'group2'}),
('JG', {'group': 'group2'}),
('JA', {'group': 'group2'}),
('JB', {'group': 'group4'}),
('JC', {'group': 'group4'}),
('RR', {'group': 'group3'}),
('RS', {'group': 'group3'}),
('TTI', {'group': 'group3'}),
('RB', {'group': 'group1'}),
('RL', {'group': 'group3'}),
('RO', {'group': 'group4'}),
('LHA', {'group': 'group2'}),
('LHI', {'group': 'group1'}),
('GF', {'group': 'group2'}),
('GB', {'group': 'group4'}),
('EM', {'group': 'group2'}),
('HR', {'group': 'group5'}),
('BS', {'group': 'group3'}),
('HH', {'group': 'group4'}),
('HA', {'group': 'group1'}),
('PS', {'group': 'group1'}),
('PW', {'group': 'group1'}),
('PB', {'group': 'group1'}),
('PC', {'group': 'group5'}),
('MFR', {'group': 'group4'}),
('JMA', {'group': 'group5'}),
('PN', {'group': 'group4'}),
('PL', {'group': 'group3'}),
('ZL', {'group': 'group4'}),
('EB', {'group': 'group2'}),
('ET', {'group': 'group3'}),
('EW', {'group': 'group1'}),
('ER', {'group': 'group3'}),
('MF', {'group': 'group3'}),
('MA', {'group': 'group4'}),
('MM', {'group': 'group2'}),
('MN', {'group': 'group4'}),
('MH', {'group': 'group3'}),
('MK', {'group': 'group2'}),
('JLA', {'group': 'group2'}),
('MP', {'group': 'group1'}),
('MS', {'group': 'group4'}),
('MR', {'group': 'group4'}),
('FI', {'group': 'group5'}),
('CJ', {'group': 'group4'}),
('CO', {'group': 'group5'}),
('CM', {'group': 'group4'}),
('CB', {'group': 'group2'}),
('CG', {'group': 'group2'}),
('CF', {'group': 'group5'}),
('CD', {'group': 'group3'}),
('CS', {'group': 'group2'}),
('CP', {'group': 'group2'}),
('CV', {'group': 'group2'}),
('KC', {'group': 'group1'}),
('KB', {'group': 'group3'}),
('SY', {'group': 'group2'}),
('KF', {'group': 'group2'}),
('KD', {'group': 'group3'}),
('KH', {'group': 'group1'}),
('SW', {'group': 'group1'}),
('KL', {'group': 'group2'}),
('KP', {'group': 'group3'}),
('KW', {'group': 'group1'}),
('SM', {'group': 'group2'}),
('SB', {'group': 'group4'}),
('DJ', {'group': 'group2'}),
('DD', {'group': 'group2'}),
('DV', {'group': 'group5'}),
('BJ', {'group': 'group3'}),
('DR', {'group': 'group2'}),
('KWI', {'group': 'group4'}),
('TW', {'group': 'group2'}),
('TT', {'group': 'group2'}),
('LH', {'group': 'group3'}),
('LW', {'group': 'group3'}),
('TM', {'group': 'group3'}),
('LS', {'group': 'group3'}),
('LP', {'group': 'group2'}),
('TG', {'group': 'group3'}),
('JCU', {'group': 'group2'}),
('AL', {'group': 'group1'}),
('AP', {'group': 'group3'}),
('AS', {'group': 'group3'}),
('IM', {'group': 'group4'}),
('AW', {'group': 'group3'}),
('HHI', {'group': 'group1'})]
In [59]:
g.edges(data=True)
Out[59]:
[('BD', 'ZL', {}),
('BD', 'JCU', {}),
('BD', 'DJ', {}),
('BD', 'BA', {}),
('BD', 'CB', {}),
('BD', 'CG', {}),
('BD', 'AS', {}),
('BD', 'MH', {}),
('BD', 'AP', {}),
('BD', 'HH', {}),
('BD', 'TM', {}),
('BD', 'CF', {}),
('BD', 'CP', {}),
('BD', 'DR', {}),
('BD', 'CV', {}),
('BD', 'EB', {}),
('WC', 'JCU', {}),
('WC', 'JS', {}),
('BA', 'JR', {}),
('BA', 'JB', {}),
('BA', 'RR', {}),
('BA', 'RS', {}),
('BA', 'LH', {}),
('BA', 'PC', {}),
('BA', 'TTI', {}),
('BA', 'PL', {}),
('BA', 'JCU', {}),
('BA', 'CF', {}),
('BA', 'EB', {}),
('BA', 'GF', {}),
('BA', 'AS', {}),
('BA', 'IM', {}),
('BA', 'BJ', {}),
('BA', 'CS', {}),
('BA', 'KH', {}),
('BA', 'SW', {}),
('BA', 'MH', {}),
('BA', 'MR', {}),
('BA', 'HHI', {}),
('WM', 'EM', {}),
('WM', 'JCU', {}),
('WM', 'CO', {}),
('WM', 'LP', {}),
('WM', 'AW', {}),
('WM', 'KD', {}),
('WM', 'TT', {}),
('WM', 'JS', {}),
('WM', 'PB', {}),
('WM', 'JM', {}),
('WM', 'MFR', {}),
('WM', 'RB', {}),
('WM', 'MR', {}),
('WM', 'DV', {}),
('WM', 'TG', {}),
('WM', 'JF', {}),
('WM', 'JMA', {}),
('WM', 'FI', {}),
('WM', 'JB', {}),
('JR', 'GF', {}),
('JR', 'MFR', {}),
('JR', 'KH', {}),
('JR', 'JB', {}),
('JS', 'EM', {}),
('JS', 'PS', {}),
('JS', 'MF', {}),
('JS', 'JCU', {}),
('JS', 'KD', {}),
('JS', 'MH', {}),
('JS', 'TTI', {}),
('JS', 'RB', {}),
('JS', 'TG', {}),
('JL', 'KB', {}),
('JL', 'MN', {}),
('JL', 'LW', {}),
('JL', 'CS', {}),
('JL', 'ET', {}),
('JL', 'ER', {}),
('JM', 'EM', {}),
('JM', 'PS', {}),
('JM', 'KD', {}),
('JM', 'CD', {}),
('JM', 'JK', {}),
('JM', 'TG', {}),
('JM', 'RO', {}),
('JM', 'CV', {}),
('JK', 'HR', {}),
('JK', 'PS', {}),
('JF', 'EM', {}),
('JF', 'PS', {}),
('JF', 'LP', {}),
('JF', 'LHA', {}),
('JF', 'CD', {}),
('JF', 'RB', {}),
('JF', 'JG', {}),
('JF', 'KF', {}),
('JG', 'CJ', {}),
('JG', 'SY', {}),
('JG', 'KF', {}),
('JG', 'LHA', {}),
('JG', 'CD', {}),
('JG', 'RB', {}),
('JG', 'BS', {}),
('JA', 'CS', {}),
('JB', 'KC', {}),
('JB', 'JCU', {}),
('JB', 'MA', {}),
('JB', 'AW', {}),
('JB', 'KWI', {}),
('JB', 'KH', {}),
('JB', 'CF', {}),
('JB', 'EB', {}),
('JB', 'PB', {}),
('JB', 'MFR', {}),
('JB', 'KW', {}),
('JB', 'RB', {}),
('JB', 'MR', {}),
('JB', 'RL', {}),
('JB', 'FI', {}),
('JB', 'JMA', {}),
('JC', 'SM', {}),
('RR', 'MS', {}),
('RR', 'SW', {}),
('RR', 'LH', {}),
('RS', 'LH', {}),
('TTI', 'JCU', {}),
('TTI', 'SW', {}),
('TTI', 'CF', {}),
('RB', 'EM', {}),
('RB', 'PS', {}),
('RB', 'SY', {}),
('RB', 'JCU', {}),
('RB', 'KD', {}),
('RB', 'CF', {}),
('RB', 'LHI', {}),
('RB', 'CD', {}),
('RB', 'MH', {}),
('RB', 'CJ', {}),
('RB', 'TG', {}),
('RB', 'EB', {}),
('RO', 'PS', {}),
('LHA', 'CJ', {}),
('LHA', 'SY', {}),
('LHA', 'KF', {}),
('LHA', 'CD', {}),
('LHI', 'PS', {}),
('LHI', 'CJ', {}),
('GF', 'KC', {}),
('GF', 'MA', {}),
('GB', 'HR', {}),
('GB', 'MM', {}),
('GB', 'LS', {}),
('EM', 'LP', {}),
('EM', 'DV', {}),
('EM', 'TG', {}),
('HR', 'MM', {}),
('HR', 'MH', {}),
('HR', 'EB', {}),
('HR', 'LS', {}),
('BS', 'CD', {}),
('HH', 'ZL', {}),
('HH', 'CB', {}),
('HH', 'CP', {}),
('HH', 'DR', {}),
('HH', 'CV', {}),
('HA', 'SM', {}),
('PS', 'KD', {}),
('PS', 'CF', {}),
('PS', 'TG', {}),
('PW', 'CM', {}),
('PW', 'TW', {}),
('PW', 'TT', {}),
('PW', 'MH', {}),
('PW', 'AL', {}),
('PW', 'MP', {}),
('PW', 'CS', {}),
('PW', 'HHI', {}),
('PW', 'EW', {}),
('PB', 'CO', {}),
('PB', 'KH', {}),
('PB', 'CF', {}),
('PB', 'MFR', {}),
('PB', 'AW', {}),
('PB', 'MA', {}),
('PC', 'CS', {}),
('PC', 'JCU', {}),
('PC', 'SW', {}),
('MFR', 'KC', {}),
('MFR', 'JCU', {}),
('MFR', 'KH', {}),
('MFR', 'MH', {}),
('MFR', 'MR', {}),
('JMA', 'KWI', {}),
('JMA', 'AW', {}),
('PN', 'SB', {}),
('PL', 'HHI', {}),
('PL', 'MK', {}),
('PL', 'LH', {}),
('ZL', 'CB', {}),
('ZL', 'AP', {}),
('ZL', 'CP', {}),
('ZL', 'DR', {}),
('ZL', 'CV', {}),
('EB', 'JCU', {}),
('EB', 'DJ', {}),
('EB', 'CM', {}),
('EB', 'SW', {}),
('EB', 'MM', {}),
('EB', 'LS', {}),
('EB', 'CS', {}),
('EB', 'CP', {}),
('EB', 'CV', {}),
('ET', 'LW', {}),
('ET', 'ER', {}),
('ET', 'KB', {}),
('EW', 'TW', {}),
('EW', 'TT', {}),
('EW', 'HHI', {}),
('EW', 'AL', {}),
('ER', 'LW', {}),
('ER', 'KB', {}),
('MA', 'KW', {}),
('MA', 'AW', {}),
('MA', 'MR', {}),
('MM', 'LS', {}),
('MH', 'JCU', {}),
('MH', 'SY', {}),
('MH', 'DJ', {}),
('MH', 'CM', {}),
('MH', 'AL', {}),
('MH', 'SW', {}),
('MH', 'CF', {}),
('MH', 'LS', {}),
('MH', 'CS', {}),
('MH', 'TG', {}),
('MH', 'CP', {}),
('MH', 'CV', {}),
('MK', 'LH', {}),
('MK', 'KL', {}),
('MK', 'JLA', {}),
('MK', 'MS', {}),
('MK', 'CS', {}),
('JLA', 'CM', {}),
('JLA', 'KL', {}),
('JLA', 'MS', {}),
('JLA', 'CS', {}),
('JLA', 'SB', {}),
('JLA', 'HHI', {}),
('MP', 'TW', {}),
('MP', 'TT', {}),
('MP', 'HHI', {}),
('MS', 'CS', {}),
('MS', 'HHI', {}),
('FI', 'KW', {}),
('FI', 'AW', {}),
('FI', 'CF', {}),
('CJ', 'SY', {}),
('CJ', 'DD', {}),
('CJ', 'CD', {}),
('CO', 'AW', {}),
('CM', 'TW', {}),
('CM', 'TT', {}),
('CM', 'AL', {}),
('CM', 'CS', {}),
('CB', 'DJ', {}),
('CB', 'CP', {}),
('CB', 'CV', {}),
('CG', 'CF', {}),
('CF', 'JCU', {}),
('CF', 'AW', {}),
('CF', 'KH', {}),
('CF', 'LH', {}),
('CF', 'AP', {}),
('CF', 'AS', {}),
('CF', 'KW', {}),
('CF', 'CS', {}),
('CF', 'CV', {}),
('CD', 'SY', {}),
('CD', 'LP', {}),
('CD', 'KF', {}),
('CS', 'JCU', {}),
('CS', 'TW', {}),
('CS', 'TT', {}),
('CS', 'AS', {}),
('CS', 'LH', {}),
('CS', 'SB', {}),
('CS', 'HHI', {}),
('CP', 'DJ', {}),
('CP', 'AP', {}),
('CP', 'DR', {}),
('CP', 'CV', {}),
('CV', 'DJ', {}),
('CV', 'AP', {}),
('CV', 'DR', {}),
('KB', 'LW', {}),
('SY', 'KF', {}),
('KF', 'AP', {}),
('KD', 'TG', {}),
('SW', 'BJ', {}),
('SW', 'IM', {}),
('SW', 'LH', {}),
('KL', 'TT', {}),
('KP', 'TM', {}),
('KW', 'JCU', {}),
('SB', 'AL', {}),
('DJ', 'TG', {}),
('BJ', 'IM', {}),
('KWI', 'AW', {}),
('TW', 'TT', {}),
('TW', 'AL', {}),
('TW', 'HHI', {}),
('TT', 'AL', {}),
('TT', 'HHI', {}),
('LH', 'JCU', {}),
('JCU', 'AP', {}),
('JCU', 'AS', {}),
('AL', 'HHI', {})]
Here is an example of how to use a colormap. It's a little tricky. If you want a customized discrete colormap you can try this SO answer Matplotlib discrete colorbar
import matplotlib.pyplot as plt
# create number for each group to allow use of colormap
from itertools import count
# get unique groups
groups = set(nx.get_node_attributes(g,'group').values())
mapping = dict(zip(sorted(groups),count()))
nodes = g.nodes()
colors = [mapping[g.node[n]['group']] for n in nodes]
# drawing nodes and edges separately so we can capture collection for colobar
pos = nx.spring_layout(g)
ec = nx.draw_networkx_edges(g, pos, alpha=0.2)
nc = nx.draw_networkx_nodes(g, pos, nodelist=nodes, node_color=colors,
with_labels=False, node_size=100, cmap=plt.cm.jet)
plt.colorbar(nc)
plt.axis('off')
plt.show()