【问题标题】:How to efficiently compute moving average in python如何在python中有效地计算移动平均线
【发布时间】:2017-12-19 09:29:35
【问题描述】:

我正在寻找一种方法来计算 3d Numpy 数组中每个给定值的平均值,其中 20 个值在正上方的行中,20 个值在正下方的行中。这类似于我之前提出的问题 (Taking minimum value of each entry +- 10 rows either side in numpy array),但计算的是 41 个值的平均值,而不是 21 个值的最小值。

我尝试过使用Scipy's uniform 1d filter,但这没有正确处理靠近数组边缘的值的模式。数组外部的窗口不应包含在平均值计算中(即在数组的底部/顶部位置,平均值应分别取自边缘值和上方/下方的 20 行)。

有没有使用统一过滤器的方法,或者有替代方法可以实现这一点?

谢谢。

编辑: Numpy 数组的尺寸为 20x3200x18,所以我一直在寻找一个相对有效的解决方案。

【问题讨论】:

    标签: python arrays numpy scipy mean


    【解决方案1】:

    如果您真的在寻找性能,您可以利用cumsum 以便只需计算一次总和,这将使实现速度提高大约 40 倍。

    请参阅下面的示例。如果没有您的确切数据和参考实现,我无法验证这是否完全符合您的要求,但它在精神上应该是正确的。

    import numpy as np
    import matplotlib.pyplot as plt
    
    arr = np.random.rand(20, 3200, 18)
    n = 20
    
    cumsum = np.cumsum(arr, axis=1)
    
    means_lower = cumsum[:, :n, :] / np.arange(1, n + 1)[None, :, None]
    means_middle = (cumsum[:, 2 * n:, :] - cumsum[:, :-2 * n , :]) / (2 * n)
    means_upper = (cumsum[:, -1, :][:, None, :] - cumsum[:, -n - 1:-1, :]) / np.arange(n, 0, -1)[None, :, None]
    
    means = np.concatenate([means_lower, means_middle, means_upper], axis=1)
    
    x = np.arange(3200)
    
    plt.plot(x, means[0, :, 0])
    

    【讨论】:

      【解决方案2】:

      您可以使用scipy.signal.convolve 来执行此操作。

      import scipy.signal as sig
      
      def windowed_mean(arr, n):
          dims = len(arr.shape)
          s = sig.convolve(arr, np.ones((2*n+1,)*dims), mode='same')
          d = sig.convolve(np.ones_like(arr), np.ones((2*n+1,)*dims), mode='same')
          return s/d
      

      基本上,s 是加窗求和,d 是加窗计数器,因此可以避免边缘错误

      【讨论】:

      • 谢谢丹尼尔。我应该提到数组很大(20x3200x18),所以我不确定卷积操作是否是我的最佳解决方案。
      • 对于大型数组,scipy.signal.fftconvolve 更快。请注意,此函数执行循环卷积,这将在边缘处为您提供与 scipy.signal.convolve 不同的行为。
      猜你喜欢
      • 2017-02-20
      • 2015-05-03
      • 2021-05-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-12-20
      • 2010-10-04
      相关资源
      最近更新 更多