matplotlib: legend does not inherit node_color from networkx graph

2.9k views Asked by At

I am running matplotlib v1.4.3 with Python 2.7 on Windows 7. When I generate a graph using networkx, the node colors passed through the node_color parameter are not being inherited by the legend. The legend's circles are the default blue color. The following code is a test case to show the issue. I am a new user to SO and not able to post images, but you can copy/paste the code to see the problem.

import networkx as nx
import matplotlib.pyplot as plt
import numpy as np

# define nodes, node types, and color range
np.random.seed(10000)
nodes = list('abcdefghijkl')
nodeTypes = ['foo','bar','baz']
nodeColors = [0.0, 0.5, 1.0]

# assign each node a type and color via a dictionaries
nodeTypeDict = dict(zip(nodeTypes, [nodes[:4],nodes[4:8],nodes[8:]]))
nodeColorDict = dict(zip(nodeTypes, nodeColors))
nodePos = dict(zip(nodes,[(np.random.random(),np.random.random()) 
                                        for i in range(len(nodes))]))

# generate the graph
g = nx.Graph()
g.add_nodes_from(nodes)

# create image canvas and axes
fig, ax = plt.subplots(1, figsize=(6,6))

# iterate each nodetype, changing colors and labels of the nodes
for nt in nodeTypes:
    # choose nodes and color for each iteration
    nlist = nodeTypeDict[nt]
    ncolor = [nodeColorDict[nt]]*len(nlist)
    # draw the graph
    nx.draw_networkx_nodes(g, 
                           pos=nodePos,
                           nodelist=nlist,
                           ax=ax, 
                           cmap=plt.cm.brg, 
                           vmin=0.0,
                           vmax=1.0,
                           node_color=ncolor,
                           label=nt)  # the label for each iteration is 
                                      # the node type

# here is the problem.  The legend does not inherit the colors.
ax.legend(scatterpoints=1)
plt.show()
1

There are 1 answers

2
Joel On

Here's a version that works.

import networkx as nx
import matplotlib.pyplot as plt
import numpy as np

# define nodes, node types, and color range
np.random.seed(10000)
nodes = list('abcdefghijkl')
nodeTypes = ['foo','bar','baz']
nodeColors = ['r', 'b', 'k']

# assign each node a type and color via a dictionaries
nodeTypeDict = dict(zip(nodeTypes, [nodes[:4],nodes[4:8],nodes[8:]]))
nodeColorDict = dict(zip(nodeTypes, nodeColors))
nodePos = dict(zip(nodes,[(np.random.random(),np.random.random()) 
                                        for i in range(len(nodes))]))

# generate the graph
g = nx.Graph()
g.add_nodes_from(nodes)

# create image canvas and axes
fig, ax = plt.subplots(1, figsize=(6,6))

# iterate each nodetype, changing colors and labels of the nodes
for nt in nodeTypes:
    # choose nodes and color for each iteration
    nlist = nodeTypeDict[nt]
    ncolor = nodeColorDict[nt]
    print ncolor
    # draw the graph
    nx.draw_networkx_nodes(g, 
                           pos=nodePos,
                           nodelist=nlist,
                           ax=ax, 
                           node_color=ncolor,
                           label=nt)  # the label for each iteration is 
                                      # the node type

# here is the problem.  The legend does not inherit the colors.
ax.legend(scatterpoints=1)
plt.savefig('tmp.png')

enter image description here

I thought I had a quick explanation of what was wrong, but I don't really. First - if you're making all the colors the same for a particular command, there's no need to send a list of colors to the draw_networkx_nodes. Just change that to a single color. I thought that would fix it, but then I ran into trouble with the cmap. I then explicitly stated what color to use, and the problem was fixed.

So - what I've got works, and it appears to be that when it draws the legend it doesn't get the right color as encoded by the color map. I recommend determining the color before the call to draw_networkx_nodes and just sending the color.