我正在寻找一种计算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,因此我一直在寻找一种相对有效的解决方案。
答案 0 :(得分:1)
您可以使用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
是窗口计数器,因此您可以避免边缘出错
答案 1 :(得分: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])