繁体   English   中英

在 matplotlib 中为茎图设置动画

[英]animating a stem plot in matplotlib

我正在尝试在 matplotlib 中为茎图设置动画,但找不到必要的文档来帮助我。 我有一系列数据文件,每个文件如下所示:

1 0.345346
2 0.124325
3 0.534585

我想将每个文件绘制为一个单独的框架。

根据thisthis other tutorial,我应该创建一个函数来更新每个绘图对象中包含的数据(艺术家?我不确定术语)

从第二个链接,这是更新功能

def update(frame):
global P, C, S

# Every ring is made more transparent
C[:,3] = np.maximum(0, C[:,3] - 1.0/n)

# Each ring is made larger
S += (size_max - size_min) / n

# Reset ring specific ring (relative to frame number)
i = frame % 50
P[i] = np.random.uniform(0,1,2)
S[i] = size_min
C[i,3] = 1

# Update scatter object
scat.set_edgecolors(C)
scat.set_sizes(S)
scat.set_offsets(P)

# Return the modified object
return scat,

如何为茎图调整这种更新函数? stem文档非常简短(实际上这是我学习 matplotlib 时经常出现的问题),但 示例代码显示stem的输出是元组markerline, stemlines, baseline而不是像plt.plot那样的艺术家对象plt.plotplt.imshow

因此,当我为动画编写update函数时,如何更新茎图中的数据?

干得好!

import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation

import numpy as np

fig, ax = plt.subplots()
x = np.linspace(0.1, 2*np.pi, 10)
markerline, stemlines, baseline = ax.stem(x, np.cos(x), '-.')

def update(i):
    ax.cla()
    markerline, stemlines, baseline = ax.stem(x, np.cos(x+i/10), '-.')
    ax.set_ylim((-1, 1))

anim = FuncAnimation(fig, update, frames=range(10, 110, 10), interval=500)
anim.save('so.gif', dpi=80, writer='imagemagick')

我认为可以有更好的方法来实现这一点 - 不需要每次都清除情节。 但是,这有效!

在此处输入图片说明

当使用关键字use_line_collection=True (自 Matplotlib 3.3 以来的默认行为)时,可以更新三个元素

  • 标记线
  • 干线
  • 基线

个人。 这是正弦波示例的代码:

import numpy as np
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation

fig, ax = plt.subplots()
x = np.linspace(0.1, 2*np.pi, 10)
y = np.cos(x)
bottom = 0
h_stem = ax.stem(x, y, bottom=bottom, use_line_collection=True, linefmt='-.')

def update(i):
    y = np.cos(x+i/10)

    # markerline
    h_stem[0].set_ydata(y)
    h_stem[0].set_xdata(x)  # not necessary for constant x 

    # stemlines
    h_stem[1].set_paths([np.array([[xx, bottom], 
                                   [xx, yy]]) for (xx, yy) in zip(x, y)])

    # baseline
    h_stem[2].set_xdata([np.min(x), np.max(x)])
    h_stem[2].set_ydata([bottom, bottom])  # not necessary for constant bottom

anim = FuncAnimation(fig, update, frames=range(10, 110, 10), interval=1)
anim.save('so.gif', dpi=80, writer='imagemagick')

根据应该更新哪些值(x, y, bottom)您可以省略此更新的某些部分或重用当前值。 我编写了一个更通用的函数,您可以在其中传递这些值的任意组合:

def update_stem(h_stem, x=None, y=None, bottom=None):
    if x is None:
        x = h_stem[0].get_xdata()
    else:
        h_stem[0].set_xdata(x)
        h_stem[2].set_xdata([np.min(x), np.max(x)])

    if y is None:
        y = h_stem[0].get_ydata()
    else:
        h_stem[0].set_ydata(y)

    if bottom is None:
        bottom = h_stem[2].get_ydata()[0]
    else:
        h_stem[2].set_ydata([bottom, bottom])

    h_stem[1].set_paths([np.array([[xx, bottom], 
                                   [xx, yy]]) for (xx, yy) in zip(x, y)])


暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM