33

I am relatively new to networkx and plotting using matplotlib.pyplot and would like to know how to modify the color (or other attributes such as weight) of a node's outline. By "outline" I don't mean an arc or edge between two nodes; I mean the thin black line around the circle that is by default used to represent a node when plotting a network.

So for example, when I make a graph that has just a single node and display it:

from networkx import *
import matplotlib.pyplot as plt
plt.ion()
G = Graph()
G.add_node(1)
draw(G)

I see a single red node with a thin black outline (and a black "1" inside it, which is the node's label). How can I change the color of that outline from black to, say, red ("#FF0000"), or another color? Alternatively, can I suppress the display of the outline entirely?

I'm imagining there must be an attribute, analogous to edge_color or node_color, that I can set. However, I was not able to find such an attribute via a web search, in the networkx documentation, or by looking at gallery examples. If someone can point me to the appropriate attribute(s) that would be greatly appreciated. Thanks!

user1071516
  • 495
  • 1
  • 5
  • 8
  • 1
    `draw` calls `draw_networkx` see http://networkx.github.io/documentation/latest/reference/generated/networkx.drawing.nx_pylab.draw_networkx.html#networkx.drawing.nx_pylab.draw_networkx, you can set the `edge_color` param to whatever you like – EdChum Mar 28 '14 at 14:58
  • 3
    `edge_color` only sets the graph edge color, while the question refers to the node outlines (comparable to `marker_edge_color` or `mec` for line graphs in pyplot). I'm looking, but haven't yet found a good solution... – groundlar Mar 28 '14 at 15:05
  • @surfreak Ah yes, sorry my mistake, don't have an answer immediately then, will dig around – EdChum Mar 28 '14 at 15:09
  • 6
    Since NetworkX 2.1, there's an `edgecolors` argument added to `draw_networkx_nodes()` as stated [below](https://stackoverflow.com/a/50016020). – Marc Apr 25 '18 at 07:06

4 Answers4

27

UPDATE (3/2019): as of networkx 2.1, the kwargs are forwarded from draw(), so you should be able to simply call draw() with the edge_color kwarg.

Ok, this is kind of hacky, but it works. Here's what I came up with.

The Problem

networkx.draw() calls networkx.draw_networkx_nodes(), which then calls pyplot.scatter() to draw the nodes. The problem is that the keyword args accepted by draw_networkx_nodes() aren't passed on to scatter(). (source here)


To solve this, I basically broke apart networkx.draw() into its components: draw_networkx_nodes, draw_networkx_edges, and draw_networkx_labels.

The Solution

We can take the return value of draw_networkx_nodes() -- a PathCollection -- and operate on that: you can use PathCollection.set_edgecolor() or PathCollection.set_edgecolors() with either a color or a list, respectively.

Example code:

from networkx import *
import matplotlib.pyplot as plt
G = Graph()
G.add_node(1)
# Need to specify a layout when calling the draw functions below
# spring_layout is the default layout used within networkx (e.g. by `draw`)
pos = spring_layout(G)
nodes = draw_networkx_nodes(G, pos)
# Set edge color to red
nodes.set_edgecolor('r')
draw_networkx_edges(G, pos)
# Uncomment this if you want your labels
## draw_networkx_labels(G, pos)
plt.show()

If you're going to be using this a lot, it probably makes more sense (IMO) to just redefine draw_networkx_nodes to actually pass the kwargs to scatter. But the above will work.

To remove the marker edges entirely, simply set the color to None instead of 'r'.

Community
  • 1
  • 1
groundlar
  • 878
  • 1
  • 8
  • 17
  • 2
    Does anyone see a reason why the kwargs **shouldn't** be passed to scatter? If not, I'll submit a bug report. – groundlar Mar 28 '14 at 16:16
  • Please do submit a bug report. I think the kwargs weren't passed to avoid conflict/confusion of similar arguments to draw_networkx_edges() etc. The drawing interface to matplotlib is crufty and could use a proper design. – Aric Mar 28 '14 at 17:13
  • Thanks, @surfreak, for the explanation and example code. Never have I been so happy to see a small red dot (i.e., you're right, it works). – user1071516 Mar 29 '14 at 14:31
  • @Aric: agreed that the drawing interface could use some work, although mine is the opinion of a noob. – user1071516 Mar 29 '14 at 14:32
  • @user1071516 You can directly access the PathCollection object when using nx.draw(), see my answer below. – jrjc Mar 28 '17 at 17:06
  • 2
    @surfreak, In 2.2 there is also the karg `edgecolors` for `draw_networkx_nodes()`. – Sigur May 27 '19 at 17:12
  • 5
    I think the update to this answer is wrong. `edge_color` argument in `draw()` sets the color of the edges = links in the graph, not the edges of the nodes – Przemysław Czechowski Jun 06 '19 at 13:53
21

Since NetworkX 2.1, there's an edgecolors argument added to draw_networkx_nodes()(as well as to draw() since it ultimately calls draw_networkx_nodes() to draw nodes).

Marc
  • 1,630
  • 1
  • 15
  • 17
17

If you want to change the color of the nodes' outline, you can just do:

draw(G, linewidths=2)
ax = plt.gca() # to get the current axis
ax.collections[0].set_edgecolor("#FF0000") 

And that's it.

  • ax.collections[0] is a PathCollection object governing the nodes
  • ax.collections[1] is a LineCollection object governing the edges if you have some.

You can modify many other properties rapidly with a given collection.

jrjc
  • 21,103
  • 9
  • 64
  • 78
4

I know this is an antient thread, but I was looking for this answer too, and finally found the native non-hacky way. You can pass the argument linewidths=0 into the draw function. I think this only affects the width of the node borders rather than the edge width (which is controled by width=x).

  • 1
    This is the way, thanks, it's only strange they didn't give the parameter a better name – Chris_Rands Mar 31 '17 at 15:16
  • Strangely, although I clearly thought this answer was very helpful last year, encountering the same issue now, I can't make sense of it – Chris_Rands Aug 21 '18 at 19:51