【问题标题】:animating a stem plot in matplotlib在 matplotlib 中为茎图制作动画
【发布时间】:2017-07-06 01:03:57
【问题描述】:

我正在尝试在 matplotlib 中为茎图制作动画,但找不到必要的文档来帮助我。我有一系列数据文件,每个文件看起来像这样:

1 0.345346
2 0.124325
3 0.534585

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

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

从第二个链接来看,这是更新函数

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,

我怎样才能使这种更新功能适用于茎图? stemdocumentation 非常简短(实际上这是我正在学习 matplotlib 时反复出现的问题),但 example code 表明 stem 的输出是元组 markerline, stemlines, baseline 而不是艺术家对象,例如 plt.plotplt.imshow

那么,当我为动画编写 update 函数时,如何更新主干图中的数据?

【问题讨论】:

    标签: python animation matplotlib plot


    【解决方案1】:

    给你!

    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')
    

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

    【讨论】:

    • 好的,所以你建议清除情节并在每一帧重绘。这将工作,谢谢!我发现学习 matplotlib 很困难,因为文档很少。我通常可以将示例拼凑在一起,但我并不真正了解所有机制。比如axes和artist的区别等等。你知道matplotlib中的逻辑和结构的解释资源吗?
    【解决方案2】:

    当使用关键字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)])
    
    
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-08-23
      • 1970-01-01
      • 1970-01-01
      • 2018-06-26
      • 2022-01-22
      • 1970-01-01
      • 2021-06-23
      相关资源
      最近更新 更多