1

我正在使用 matplotlib 动画探索实时图表。目前,我只是将一个随机整数添加到一个数组中,并根据新数字更新我的绘图。问题是我似乎得到了情节的额外价值。

我有以下代码:

import matplotlib.pyplot as plt
import matplotlib.animation as animation
import random

fig = plt.figure()
ax1 = fig.add_subplot(1, 1, 1)

xs = []
ys = []

def animate(i, xs, ys):
    
    x = i + 1
    y = random.randint(1, 50)
    
    print '{}: {}, {}'.format(i, x, y)
    
    xs.append(x)
    ys.append(y)
            
    ax1.clear()
    ax1.plot(xs, ys)
        
ani = animation.FuncAnimation(fig,
                              animate,
                              frames = 10,
                              fargs = (xs, ys),
                              repeat = False)
plt.show()

我只想绘制 10 个值,所以我frames = 10FuncAnimate调用中设置。但是,打印语句输出第 11 个值:

绘图结果

打印语句输出

所以很明显正在生成 11 帧,而不是 10 帧。查看 FuncAnimate 的文档,我看不出发生这种情况的原因。

谁能告诉我我错过了什么?

谢谢!

4

1 回答 1

2

也许这不是解决它的最优雅的方法,但您可以使用标志作为解决方法,以避免在第一个循环中运行动画:

import matplotlib.pyplot as plt
import matplotlib.animation as animation
import random

fig = plt.figure()
ax1 = fig.add_subplot(1, 1, 1)

xs = []
ys = []

flag = 0
def animate(i, xs, ys):

    global flag

    if i == 0 and flag == 0:
        flag = 1
        return

    if flag == 1:
        x = i + 1
        y = random.randint(1, 50)

        print '{}: {}, {}'.format(i, x, y)

        xs.append(x)
        ys.append(y)

        ax1.clear()
        ax1.plot(xs, ys)


ani = animation.FuncAnimation(fig,
                              animate,
                              frames = 10,
                              fargs = (xs, ys),
                              repeat = False)
plt.show()

输出:

0: 1, 37
1: 2, 2
2: 3, 46
3: 4, 39
4: 5, 30
5: 6, 47
6: 7, 16
7: 8, 3
8: 9, 3
9: 10, 49

阴谋:

在此处输入图像描述


编辑
我做了一些研究。这种行为是由于您(和我)没有init_func指定FuncAnimation. 正如您可以从文档中看到的:

init_func: callable, optional 用于绘制清晰边框的函数。如果未给出,将使用从帧序列中的第一项绘制的结果。此函数将在第一帧之前调用一次。所需的签名是:

def init_func() -> iterable_of_artists

如果blit == Trueinit_func必须返回一个可迭代的艺术家以重新绘制。位图算法使用此信息来确定图形的哪些部分必须更新。blit == False如果在这种情况下可以省略返回值,则返回值是未使用的。

如果不指定init_func,则重复第一帧(用作初始化帧)。
也就是说,我认为避免重复的最正确方法是调用一个init不绘制任何内容的函数:

import matplotlib.pyplot as plt
import matplotlib.animation as animation
import random

fig = plt.figure()
ax1 = fig.add_subplot(1, 1, 1)

xs = []
ys = []

def init():
    ax1.clear()

def animate(i, xs, ys):
    x = i + 1
    y = random.randint(1, 50)

    print '{}: {}, {}'.format(i, x, y)

    xs.append(x)
    ys.append(y)

    ax1.clear()
    ax1.plot(xs, ys)


ani = animation.FuncAnimation(fig = fig,
                              func = animate,
                              init_func = init,
                              frames = 10,
                              fargs = (xs, ys),
                              repeat = False)

plt.show()

输出:

0: 1, 12
1: 2, 25
2: 3, 20
3: 4, 49
4: 5, 49
5: 6, 28
6: 7, 26
7: 8, 49
8: 9, 10
9: 10, 2

动画:

在此处输入图像描述

于 2020-07-02T12:26:24.483 回答