使用 NetworkX 和 Matplotlib 动画网络增长

Posted

技术标签:

【中文标题】使用 NetworkX 和 Matplotlib 动画网络增长【英文标题】:Animating Network Growth with NetworkX and Matplotlib 【发布时间】:2012-11-06 09:35:56 【问题描述】:

我想制作一个随时间增长的图表。

这是我目前所拥有的:

fig = plt.figure()
ims = []
graph = nx.Graph()
for i in range(50):
    // Code to modify Graph
    nx.draw(graph, pos=nx.get_node_attributes(graph,'Position'))
    im = plt.draw()
    self.ims.append([im])
ani = animation.ArtistAnimation(fig, ims, interval=50, blit=True,repeat_delay=1000)
ani.save('dynamic_images.mp4')
plt.show()

但是,我收到以下错误消息:

 File "main.py", line 204, in <module>
    repeat_delay=1000)
  File "/usr/lib/pymodules/python2.7/matplotlib/animation.py", line 356, in __init__
    TimedAnimation.__init__(self, fig, *args, **kwargs)
  File "/usr/lib/pymodules/python2.7/matplotlib/animation.py", line 304, in __init__
    Animation.__init__(self, fig, event_source=event_source, *args, **kwargs)
  File "/usr/lib/pymodules/python2.7/matplotlib/animation.py", line 53, in __init__
    self._init_draw()
  File "/usr/lib/pymodules/python2.7/matplotlib/animation.py", line 363, in _init_draw
    artist.set_visible(False)
AttributeError: 'NoneType' object has no attribute 'set_visible'
nicomoto@nicomoto-VirtualBox:~/Desktop/CS8903-SpecialProblem/Code/

我想要的是一个动画,你可以在其中看到图形的增长。我可以在每个阶段保存图表,也许可以在 matplotlib 之外创建动画,但是有什么办法让它像这样工作吗?

【问题讨论】:

你的后端是什么?我遇到了一些后端的动画问题。你能运行matplotlib的basic_example.py吗? 是的,这对我来说非常适合。至于后端,我只是在ubuntu,python 2.7,numpy,scipy,networkx和matplotlib上......都是最近几天安装的,所以它们是最新版本......我基本上是个学生,正在尝试一些实验,对这些图表进行动画处理真的很有帮助,所以我可以看到它们是如何成长的! 我对networkx不熟悉。也许问题是ArtistAnimation 需要一个 matplotlib 艺术家而不是一个 nx 对象? 更新了我的答案,希望对你有帮助。 【参考方案1】:

经过审查,该代码与我想象的这个问题的相关性并不高。但是,我可以使用this SO answer 和this SO answer 为您拼凑出答案。下面的代码将创建一个图形,向其中添加 50 个随机节点和 50 个随机边,并在添加每个节点和边后显示图形的图像。代码中的一些关键更改:

    此代码基于使用 pylab.ion()(有关详细信息,请参阅 here)。 您的代码尝试使用一个图形并更改其中的图像。此代码为每一帧创建一个新图形。 此代码不会写入 .mp4。如果您确实需要这样做,我建议您在渲染时将这些数字写入 .png 文件,然后再转换为 mp4。 请注意,此代码使用matplotlib.pyplot.pause() 而不是time.sleep()。如果您使用time.sleep(),这些数字将不会呈现。

祝你好运!

import random
import pylab
from matplotlib.pyplot import pause
import networkx as nx
pylab.ion()

graph = nx.Graph()
node_number = 0
graph.add_node(node_number, Position=(random.randrange(0, 100), random.randrange(0, 100)))

def get_fig():
    global node_number
    node_number += 1
    graph.add_node(node_number, Position=(random.randrange(0, 100), random.randrange(0, 100)))
    graph.add_edge(node_number, random.choice(graph.nodes()))
    fig = pylab.figure()
    nx.draw(graph, pos=nx.get_node_attributes(graph,'Position'))
    return fig

num_plots = 50;
pylab.show()

for i in range(num_plots):

    fig = get_fig()
    fig.canvas.draw()
    pylab.draw()
    pause(2)
    pylab.close(fig)

【讨论】:

很抱歉耽搁了,不管怎样,你的建议让我想到了,这是我首先做的,我绘制了图表并存储了单独的 png,然后在外面将它们拼接在一起......我也用 ion 做了一个实现,唯一的问题是我不能将这些保存为 gif 文件,但它很酷,因为你可以看到运行时的变化 谢谢!我打算尝试使用 matplotlib.animation.FuncAnimation 的替代解决方案(有关更多信息,请参阅matplotlib.org/api/animation_api.html),但我只是没有时间。 @Skyler 这段代码已经很老了,库已经进化了。一个简单的解决方法是使用random.choice(list(graph.nodes())) 而不是random.choice(graph.nodes())。我刚刚添加了一个新的答案,说明代码现在的样子。【参考方案2】:

brtlance 的改进版本。希望它会有所帮助。它会显示动画,但不会显示一张接一张的照片

还是不知道题主如何 Animate drawing networkx edges 利用matplotlib的动画

#!/usr/bin/env python
import random
import pylab
from matplotlib.pyplot import pause
import networkx as nx
pylab.ion()

graph = nx.Graph()
node_number = 0
graph.add_node(node_number, Position=(random.randrange(0, 100), random.randrange(0, 100)))

def get_fig():
    global node_number
    node_number += 1
    graph.add_node(node_number, Position=(random.randrange(0, 100), random.randrange(0, 100)))
    graph.add_edge(node_number, random.choice(graph.nodes()))
    nx.draw(graph, pos=nx.get_node_attributes(graph,'Position'))

num_plots = 50;
pylab.show()

for i in range(num_plots):

    get_fig()
    pylab.draw()
    pause(2)

【讨论】:

正是我想要的。一幅画到另一幅画之间的过渡很好。减少暂停可以提供流畅的动画。谢谢。 :)【参考方案3】:

由于现有答案已经很老了,这里有一个版本的代码在当前版本的 matplotlib 和 networkx 下的样子。

import random
import networkx as nx
import matplotlib.pyplot as plt

graph = nx.Graph()
num_plots = 50
for node_number in range(num_plots):
    graph.add_node(node_number, Position=(random.randrange(0, 100), random.randrange(0, 100)))
    graph.add_edge(node_number, random.choice(list(graph.nodes())))
    nx.draw(graph, pos=nx.get_node_attributes(graph,'Position'))
    plt.pause(0.5)

【讨论】:

以上是关于使用 NetworkX 和 Matplotlib 动画网络增长的主要内容,如果未能解决你的问题,请参考以下文章

使用 python 和 networkx 进行大图可视化

Networkx 和 Matplotlib:如何访问节点属性并将它们显示为注释

节点的 Networkx 和 matplotlib 颜色图;不同网络的相同地图

将 NetworkX 图嵌入 PyQT 小部件

如何使用 `networkx` 中的 `pos` 参数创建流程图样式的图表? (Python 3)

[Python] networkx入门 转