【问题标题】:Animation of histograms in subplot子图中直方图的动画
【发布时间】:2017-08-12 03:29:40
【问题描述】:

我有以下动画子图来模拟四种不同分布的直方图:

import numpy
from matplotlib.pylab import *
import matplotlib.animation as animation

n = 100

# generate 4 random variables from the random, gamma, exponential, and uniform distributions
x1 = np.random.normal(-2.5, 1, 10000)
x2 = np.random.gamma(2, 1.5, 10000)
x3 = np.random.exponential(2, 10000)+7
x4 = np.random.uniform(14,20, 10000)

fig, ((ax1, ax2), (ax3, ax4)) = plt.subplots(2, 2)

def updateData(curr):

    if curr == n: 
        a.event_source.stop()

    ax1.hist(x1[:curr], normed=True, bins=20, alpha=0.5)
    ax2.hist(x2[:curr], normed=True, bins=20, alpha=0.5)
    ax3.hist(x3[:curr], normed=True, bins=20, alpha=0.5)
    ax4.hist(x4[:curr], normed=True, bins=20, alpha=0.5)

simulation = animation.FuncAnimation(fig, updateData, interval=20, repeat=False)

plt.show()

它可以工作,但由于某种原因,对于 y 轴缩放,normed=True 被忽略了。如果我将这些情节从动画中取出,它们会正确缩放。如何在动画中获得适当的缩放比例?

编辑

而不是像这样的比例(动画之外):

我得到(动画内部):

【问题讨论】:

  • 不太清楚你的意思。当我运行代码时,norm=True 在动画内外的工作方式相同。绘制新的直方图时会调整比例。
  • 我在上面包含了我的输出图像。
  • 该输出是预期的,因为您在同一个图中绘制了所有 100 个直方图。每个直方图都是规范的。究竟是什么问题?
  • 我希望动画的 y 轴刻度在 0 和 1 之间。我认为这就是 normed=True 提供的。

标签: python animation matplotlib histogram


【解决方案1】:

直方图的normed = True 参数使直方图绘制分布的密度。来自the documentation

规范:布尔值,可选
如果为True,则返回元组的第一个元素将是归一化以形成概率密度的计数,即n/(len(x)`dbin),即直方图的积分总和为1强>。如果stacked 也为True,则直方图的总和归一化为1。 默认为假

这意味着直方图条的高度取决于 bin 宽度。如果像动画开始时那样只绘制一个数据点,则条形高度将为 1./binwidth。如果 bin 宽度小于零,则条形高度可能会变得非常大。

因此,修复垃圾箱并在整个动画中使用它们是个好主意。
清除坐标轴也是合理的,这样就不会绘制 100 个不同的直方图。

import numpy as np
from matplotlib.pylab import *
import matplotlib.animation as animation

# generate 4 random variables from the random, gamma, exponential, and uniform distribution
x1 = np.random.normal(-2.5, 1, 10000)
x2 = np.random.gamma(2, 1.5, 10000)
x3 = np.random.exponential(2, 10000)+7
x4 = np.random.uniform(14,20, 10000)

fig, ((ax1, ax2), (ax3, ax4)) = plt.subplots(2, 2)

def updateData(curr):
    if curr <=2: return
    for ax in (ax1, ax2, ax3, ax4):
        ax.clear()
    ax1.hist(x1[:curr], normed=True, bins=np.linspace(-6,1, num=21), alpha=0.5)
    ax2.hist(x2[:curr], normed=True, bins=np.linspace(0,15,num=21), alpha=0.5)
    ax3.hist(x3[:curr], normed=True, bins=np.linspace(7,20,num=21), alpha=0.5)
    ax4.hist(x4[:curr], normed=True, bins=np.linspace(14,20,num=21), alpha=0.5)

simulation = animation.FuncAnimation(fig, updateData, interval=50, repeat=False)

plt.show()

【讨论】:

  • 我想跳过阅读文档值得投反对票! ^_^ 直到我意识到每次调用 updateData 都会创建一个新的直方图,我才真正理解您所说的“绘制 100 个不同的直方图”是什么意思。
  • 您能解释一下清轴的重要性吗?
  • @Zaks 正如答案中所指出的,如果您不清除轴,您最终会在轴中得到 100 个单独的直方图。 (请注意,如果您使用 blitting,情况会有所不同 - 在这种情况下,您不需要清除轴,除非您想将动画保存/导出为电影)。
  • @ImportanceOfBeingErnest 好的,我知道 funcAnimate 基本上是循环并在每个循环中重新创建直方图,但保留以前的信息。这让我问:在你的函数 UpdateData 中,(curr)是第 n 个循环,所以你基本上是在 2 处切割 FuncAnimate?非常感谢,谢谢。
  • @Ashli​​nJP 在计算值之前你无法知道它(这更像是一个哲学事实!)。但是你可以先计算所有的直方图,然后知道要设置哪个值ax.set_ylim(0, maxvalue)
【解决方案2】:

是的!我也遇到了同样的问题 如果您遇到此类问题,请不要忘记在显示动画的每一帧之前清除轴。

使用 plt.cla() 要么 ax.clear()(在你的情况下) 每个轴

在为动画定义的函数中进行绘图之前

【讨论】:

    【解决方案3】:

    知道了!

    我对 n 的迭代是罪魁祸首。这符合我的预期:

    def updateData(curr):
    
        curr2=100+curr*5 
    
        #if curr == n: 
        #    a.event_source.stop()
    
        ax1.hist(x1[:curr2], normed=True, bins=20, alpha=0.5)
        ax2.hist(x2[:curr2], normed=True, bins=20, alpha=0.5)
        ax3.hist(x3[:curr2], normed=True, bins=20, alpha=0.5)
        ax4.hist(x4[:curr2], normed=True, bins=20, alpha=0.5)
    
    simulation = animation.FuncAnimation(fig, updateData, frames=900, interval=10)
    
    plt.show()
    

    【讨论】:

      猜你喜欢
      • 2020-10-28
      • 2021-11-28
      • 2021-11-27
      • 2020-07-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-06-14
      • 2013-07-18
      相关资源
      最近更新 更多