Using NetworkX with matplotlib.ArtistAnimation

2020-01-28 09:16发布

问题:

What I want to do is create an animation in which the nodes of a graph change color with time. When I search for information on animation in matplotlib, I usually see examples that look something like this:

#!/usr/bin/python

import numpy as np
import matplotlib
import matplotlib.pyplot as plt
from matplotlib.animation import ArtistAnimation

fig = plt.figure(figsize=(8,8))
images = []
for i in range(10):
  data = np.random.random(100).reshape(10,10)
  imgplot = plt.imshow(data)
  images.append([imgplot])
anim = ArtistAnimation(fig, images, interval=50, blit=True)
anim.save('this-one-works.mp4')
plt.show()

So I thought I could just do something like this:

#!/usr/bin/python

import numpy as np
import networkx as nx
import matplotlib
import matplotlib.pyplot as plt
from matplotlib.animation import ArtistAnimation

G = nx.Graph()
G.add_edges_from([(0,1),(1,2),(2,0)])
fig = plt.figure(figsize=(8,8))
pos=nx.graphviz_layout(G)
images = []
for i in range(10):
  nc = np.random.random(3)
  imgplot = nx.draw(G,pos,with_labels=False,node_color=nc) # this doesn't work
  images.append([imgplot])
anim = ArtistAnimation(fig, images, interval=50, blit=True)
anim.save('not-this-one.mp4')
plt.show()

What I'm stuck on is how, after drawing the graph using nx.draw(), I can get an object of the appropriate type to put in the array being passed to ArtistAnimation. In the first example, plt.imshow() returns an object of type matplot.image.AxesImage, but nx.draw() doesn't actually return anything. Is there a way that I can get my hands on a suitable image object?

Completely different approaches are welcome, of course (it seems like there's always many different ways to do the same thing in matplotlib), as long as I can save my animation as an mp4 when I'm done.

Thanks!

--craig

回答1:

import numpy as np
import networkx as nx
import matplotlib
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation

G = nx.Graph()
G.add_edges_from([(0,1),(1,2),(2,0)])
fig = plt.figure(figsize=(8,8))
pos=nx.graphviz_layout(G)
nc = np.random.random(3)
nodes = nx.draw_networkx_nodes(G,pos,node_color=nc)
edges = nx.draw_networkx_edges(G,pos) 


def update(n):
  nc = np.random.random(3)
  nodes.set_array(nc)
  return nodes,

anim = FuncAnimation(fig, update, interval=50, blit=True)

nx.draw does not return anything, hence why your method didn't work. The easiest way to do this is to draw the nodes and edges using nx.draw_networkx_nodes and nx.draw_networkx_edges which return PatchCollection and LineCollection objects. You can then update the color of the nodes using set_array.

Using the same general frame work you can also move the nodes around (via set_offsets for the PatchCollection and set_verts or set_segments for LineCollection)

best animation tutorial I have seen: http://jakevdp.github.io/blog/2012/08/18/matplotlib-animation-tutorial/