Python 在 matplotlib 中使用 for 循环定义要动画的多个图

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/21937976/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-18 23:54:29  来源:igfitidea点击:

Defining multiple plots to be animated with a for loop in matplotlib

pythonanimationmatplotlib

提问by cjorssen

Thanks to Jake Vanderplas, I know how to start to code an animated plot with matplotlib. Here is a sample code:

感谢 Jake Vanderplas,我知道如何开始使用matplotlib. 这是一个示例代码:

from matplotlib import pyplot as plt
from matplotlib import animation

fig = plt.figure()

ax = plt.axes(xlim=(0, 2), ylim=(0, 100))

line, = plt.plot([], [])

def init():
    line.set_data([], [])
    return line,

def animate(i):
    line.set_data([0, 2], [0,i])
    return line,

anim = animation.FuncAnimation(fig, animate, init_func=init,
                               frames=100, interval=20, blit=True)

plt.show()

Suppose now I'd like to plot tons of functions (say four here), defined with the help of a loop. I did some voodoo programming, trying to understand how to mimic the comma following line and here is what I got (needless to say that it does not work: AttributeError: 'tuple' object has no attribute 'axes').

假设现在我想绘制大量的函数(这里说四个),在循环的帮助下定义。我做了一些巫毒编程,试图理解如何模仿下面的逗号,这就是我得到的(不用说它不起作用:)AttributeError: 'tuple' object has no attribute 'axes'

from matplotlib import pyplot as plt
from matplotlib import animation

fig = plt.figure()

ax = plt.axes(xlim=(0, 2), ylim=(0, 100))

line = []
N = 4

for j in range(N):
    temp, = plt.plot([], [])
    line.append(temp)

line = tuple(line)

def init():
    for j in range(N):
        line[j].set_data([], [])
    return line,

def animate(i):
    for j in range(N):
        line[j].set_data([0, 2], [10 * j,i])
    return line,

anim = animation.FuncAnimation(fig, animate, init_func=init,
                               frames=100, interval=20, blit=True)

plt.show()

Some my question is:how can I make it work? Bonus (probably linked): what is the difference between line, = plt.plot([], [])and line = plt.plot([], [])?

我的一些问题是:我怎样才能让它工作?奖金(可能相关):line, = plt.plot([], [])和之间有什么区别line = plt.plot([], [])

Thanks

谢谢

采纳答案by Alvaro Fuentes

In the solution below I showcase a bigger example (with also bar plot) that may help people understand better what should be done for other cases. After the code I explain some details and answer the bonus question.

在下面的解决方案中,我展示了一个更大的例子(还有条形图),它可以帮助人们更好地理解对于其他情况应该做什么。在代码之后,我解释了一些细节并回答了奖金问题。

import matplotlib
matplotlib.use('Qt5Agg') #use Qt5 as backend, comment this line for default backend

from matplotlib import pyplot as plt
from matplotlib import animation

fig = plt.figure()

ax = plt.axes(xlim=(0, 2), ylim=(0, 100))

N = 4
lines = [plt.plot([], [])[0] for _ in range(N)] #lines to animate

rectangles = plt.bar([0.5,1,1.5],[50,40,90],width=0.1) #rectangles to animate

patches = lines + list(rectangles) #things to animate

def init():
    #init lines
    for line in lines:
        line.set_data([], [])

    #init rectangles
    for rectangle in rectangles:
        rectangle.set_height(0)

    return patches #return everything that must be updated

def animate(i):
    #animate lines
    for j,line in enumerate(lines):
        line.set_data([0, 2], [10 * j,i])

    #animate rectangles
    for j,rectangle in enumerate(rectangles):
        rectangle.set_height(i/(j+1))

    return patches #return everything that must be updated

anim = animation.FuncAnimation(fig, animate, init_func=init,
                               frames=100, interval=20, blit=True)

plt.show()

Explanation

解释

The idea is to plot what you need and then reuse the artists (see more here) returned by matplotlib. This is done by first plotting a dummy sketch of what you want and keeping the objects matplotlibgives you. Then on your initand animatefunctions you can update the objects that need to be animated.

这个想法是画出你需要什么,然后再利用艺术家(详见这里)由归国matplotlib。这是通过首先绘制您想要的虚拟草图并保留matplotlib给您的对象来完成的。然后在您的initanimate函数上,您可以更新需要设置动画的对象。

Note that in plt.plot([], [])[0]we get a single line artist, thus I collect them with [plt.plot([], [])[0] for _ in range(N)]. On the other hand plt.bar([0.5,1,1.5],[50,40,90],width=0.1)returns a container that can be iterated for the rectangle artists. list(rectangles)just convert this container into a list to be concatenated with lines.

请注意,plt.plot([], [])[0]我们有一个单行艺术家,因此我用[plt.plot([], [])[0] for _ in range(N)]. 另一方面,plt.bar([0.5,1,1.5],[50,40,90],width=0.1)返回一个可以为矩形艺术家迭代的容器。list(rectangles)只需将此容器转换为要与lines.

I separate the lines from the rectangles because they are updated differently (and are different artists) but initand animatereturn all of them.

我将线条与矩形分开,因为它们的更新方式不同(并且是不同的艺术家),但是initanimate返回所有这些。

Answer to bonus question:

回答奖金问题:

  1. line, = plt.plot([], [])assign the first element of the list returned by plt.plotto the veriable line.
  2. line = plt.plot([], [])just assign the whole list (of only one element).
  1. line, = plt.plot([], [])将 返回的列表的第一个元素分配给plt.plotveriable line
  2. line = plt.plot([], [])只需分配整个列表(只有一个元素)。