如何在python中高效地计算移动平均值

如何在python中高效地计算移动平均值,python,arrays,numpy,scipy,mean,Python,Arrays,Numpy,Scipy,Mean,我正在寻找一种计算3d Numpy数组中每个给定值的平均值的方法,其中20个值在正上方的行中,20个值在正下方的行中。这类似于我之前问的问题(),但计算41个值的平均值,而不是最小值21 我尝试过使用,但这没有一种模式可以正确处理接近数组边缘的值。数组外部的窗口不应包括在平均值计算中(即,在数组的底部/顶部位置,平均值应分别取自边缘值和上面/下面的20行) 是否有任何方法可以使用均匀滤波器,或者是否有其他方法可以实现这一点 谢谢 编辑: Numpy阵列的尺寸为20x3200x18,因此我正在寻找

我正在寻找一种计算3d Numpy数组中每个给定值的平均值的方法,其中20个值在正上方的行中,20个值在正下方的行中。这类似于我之前问的问题(),但计算41个值的平均值,而不是最小值21

我尝试过使用,但这没有一种模式可以正确处理接近数组边缘的值。数组外部的窗口不应包括在平均值计算中(即,在数组的底部/顶部位置,平均值应分别取自边缘值和上面/下面的20行)

是否有任何方法可以使用均匀滤波器,或者是否有其他方法可以实现这一点

谢谢

编辑:
Numpy阵列的尺寸为20x3200x18,因此我正在寻找一种相对有效的解决方案。

您可以使用
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
是一个加窗计数器,因此您可以避免边缘错误

如果您真的希望在这方面获得性能,您可以利用
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])

谢谢你,丹尼尔。我应该提到阵列很大(20x3200x18),所以我不确定卷积操作是否是我的最佳解决方案。对于大型阵列,
scipy.signal.fftconvolve
更快。请注意,此函数执行循环卷积,这将为您提供与边缘处的
scipy.signal.convolve
不同的行为。