【问题标题】:Defining multiple plots to be animated with a for loop in matplotlib在 matplotlib 中使用 for 循环定义要动画的多个绘图
【发布时间】:2014-03-23 04:14:45
【问题描述】:

Thanks to 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()

假设现在我想绘制大量函数(这里说四个),在循环的帮助下定义。我做了一些伏都教编程,试图了解如何模仿逗号后面的行,这就是我得到的(不用说它不起作用: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([], []) 有什么区别?

谢谢

【问题讨论】:

    标签: python animation matplotlib


    【解决方案1】:

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

    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 返回的艺术家(查看更多 here)。这是通过首先绘制您想要的虚拟草图并保留matplotlib 给您的对象来完成的。然后在您的 initanimate 函数上,您可以更新需要动画的对象。

    请注意,在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 连接的列表。

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

    额外问题的答案:

    1. line, = plt.plot([], [])plt.plot 返回的列表的第一个元素分配给可验证的line
    2. line = plt.plot([], []) 只需分配整个列表(只有一个元素)。

    【讨论】:

    • 非常感谢。请问plt.plot列表的第一个元素是什么?
    • plt.plot 返回matplotlib.artist.Artists 的列表,因此当您仅绘制一行时,它会返回仅包含一项的列表:matplotlib.lines.Line2D 艺术家。但是,如果您像lines = plt.plot( *([[], []]*N) ) 那样绘制多行,它会返回列表中的所有行。
    • 谢谢。最后一个问题。 animatereturnline后面的逗号不是强制的吗?如果我正确理解您的解决方案,则没有这样的逗号。
    • 没有逗号,但请检查我是否这样做plt.plot([], [])[0] 以获得第一个值。 line, = plt.plot([], []) 语法是使用 a,b = [1,2] 上的 python 赋值的解包功能使 line = plt.plot([], [])[0] 这一行更简洁
    • 嗨,我可以问一个问题来扩展这个吗?在您的示例中,您有多个 lines 对象,但是如果我想更新 linesimage 对象会发生什么(例如更新点的位置并更新动画中的 matshow() 数组。我可以把这两个在同一个元组中?
    【解决方案2】:

    这是一个更易读的修改示例。 这只是 matplotlib 网站上添加的另一段代码。让我感到震惊的是,我最初并没有意识到 plt 函数正在返回列表,忽略尾随逗号,甚至是如何将事物联系在一起,这似乎是由库本身隐含地处理的。但关键是创建几个可更新的对象,并将它们从两个关键函数中返回,作为同一列表的一部分,并且它们将在动画运行时同步。

    import numpy as np
    import matplotlib.pyplot as plt
    from matplotlib.animation import FuncAnimation
    
    fig, ax = plt.subplots()
    xdata, ydata = [], []
    xdata2,ydata2= [], []
    ln, = plt.plot([], [], 'ro') 
    ln2, = plt.plot([], [], 'ro')
    
    def init():
        ax.set_xlim(0, 2*np.pi)
        ax.set_ylim(-1, 1)
        return ln,ln2
    
    def update(frame):
        xdata.append(frame)
        ydata.append(np.sin(frame))
        ln.set_data(xdata, ydata)
    
        xdata2.append(frame)
        ydata2.append(np.cos(frame))
        ln2.set_data(xdata2,ydata2)
        
        return ln,ln2
    
    ani = FuncAnimation(fig, update, frames=np.linspace(0, 2*np.pi, 128),
                        init_func=init, blit=True)
    
    
    plt.show()
    

    为了更有趣,将动画回调更改为以下内容:

    def update(frame):
        xdata.append(frame)
        ydata.append(np.sin(frame))
        ln.set_data(xdata, ydata)
    
        delta = 2*np.pi/128
        xdata2.append([frame*2,frame*2+delta])
        ydata2.append([np.cos(frame*2), np.cos(frame*2+delta)])
        ln2.set_data(xdata2,ydata2)
        
        return ln,ln2
    

    【讨论】:

      猜你喜欢
      • 2016-01-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-01-05
      • 1970-01-01
      • 2021-05-23
      相关资源
      最近更新 更多