在 matplotlib 中使用 for 循环定义要动画的多个图 [英] Defining multiple plots to be animated with a for loop in matplotlib
问题描述
感谢 Jake Vanderplas,我知道如何使用 matplotlib
开始编写动画图.这是一个示例代码:
Thanks to Jake Vanderplas, I know how to start to code an animated plot with matplotlib
. Here is a sample code:
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()
假设现在我想绘制大量的函数(这里说四个),在循环的帮助下定义.我做了一些伏都教编程,试图理解如何模仿下面的逗号,这就是我得到的(不用说它不起作用:AttributeError: 'tuple' object has no attribute 'axes'
).
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'
).
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()
我的一些问题是:我怎样才能让它发挥作用?奖金(可能链接):line, = plt.plot([], [])
和 line = plt.plot([], [])
之间有什么区别?>?
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([], [])
?
谢谢
推荐答案
在下面的解决方案中,我展示了一个更大的示例(还有 条形图),可以帮助人们更好地理解应该做什么其他情况.在代码之后我解释了一些细节并回答了奖金问题.
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()
说明
我们的想法是绘制您需要的内容,然后重用艺术家(查看更多此处)由 matplotlib
返回.这是通过首先绘制您想要的虚拟草图并保留 matplotlib
给您的对象来完成的.然后在您的 init
和 animate
函数中,您可以更新需要动画的对象.
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 matplotlib
gives you. Then on your init
and animate
functions you can update the objects that need to be animated.
请注意,在 plt.plot([], [])[0]
中,我们得到了一个 line 艺术家,因此我用 [plt.plot([], [])[0] for _ in range(N)]
.另一方面,plt.bar([0.5,1,1.5],[50,40,90],width=0.1)
返回一个容器,可以为 矩形艺术家强>.list(rectangles)
只是将这个容器转换成一个列表,与lines
连接起来.
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
.
我将线条与矩形分开,因为它们的更新方式不同(并且是不同的艺术家),但是 init
和 animate
返回所有这些.
I separate the lines from the rectangles because they are updated differently (and are different artists) but init
and animate
return all of them.
回答奖励问题:
line, = plt.plot([], [])
将plt.plot
返回的列表的第一个元素分配给可验证的line
.line = plt.plot([], [])
只分配整个列表(只有一个元素).
line, = plt.plot([], [])
assign the first element of the list returned byplt.plot
to the veriableline
.line = plt.plot([], [])
just assign the whole list (of only one element).
这篇关于在 matplotlib 中使用 for 循环定义要动画的多个图的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!