我有一个大的numpy数组,维度为[1]
。我想找出一种"组平均值"。更具体地说,
让我的数组为[1,2,3,4,5,6,7,8,9,10]
,让我的group_size
为3
。因此,我将平均前三个元素,第4到第6个元素,第7个到第9个元素,并平均其余元素(在这种情况下只有1个 - [2, 5, 8, 10]
。不用说,我需要一个矢量化实施
最后,我的目的是减少噪声图中的点数,以平滑具有大量振荡的一般模式。是否有正确的方式来执行此操作?我希望得到两个问题的答案,以防他们有不同的答案。谢谢!
答案 0 :(得分:2)
良好的平滑功能是kernel convolution。它的作用是在一个移动窗口中将一个小数组乘以较大的数组。
假设您选择了1/3 * [1,1,1]
的标准平滑内核并将其应用于数组(内核需要奇数编号并进行规范化)。让我们将其应用于[1,2,2,7,3,4,9,4,5,6]
:
开始的核心中心位于第一个2
。然后它平均自己和它的邻居,然后继续前进。结果是这样的:
[1.67, 3.67, 4.0, 4.67, 5.33, 5.67, 6.0, 5.0]
请注意,数组缺少第一个和最后一个元素。
您可以使用numpy.convolve执行此操作,例如:
import numpy as np
a = np.array([[1,2,2,7,3,4,9,4,5,6]])
k = np.array([1,1,1])/3
smoothed = np.convolve(x, k, 'valid')
这样做的结果是您的中心值使用其邻居的值进行平滑处理。您可以通过增加卷积内核来改变卷积内核,例如[1,1,1,1,1]/5
,或者给它一个高斯,这将比中心成员更多地强调中心成员。阅读维基百科文章。
修改强>
当问题要求时,这可以获得块平均值:
import numpy as np
a = [1,2,3,4,5,6,7,8,9,10]
size = 3
new_a = []
i = 0
while i < len(a):
val = np.mean(a[i:i+3])
new_a.append(val)
i+=size
print(new_a)
[2.0, 5.0, 8.0, 10.0]
答案 1 :(得分:2)
要解决群体平均问题,下面列出了两种方法。
方法#1:基于Bin的求和和平均值
In [77]: a
Out[77]: array([74, 48, 92, 40, 35, 38, 20, 69, 82, 37])
In [78]: N = 3 # Window size
In [79]: np.arange(a.size)//N # IDs for binning with bincount
Out[79]: array([0, 0, 0, 1, 1, 1, 2, 2, 2, 3])
In [84]: np.bincount(np.arange(a.size)//N,a)/np.bincount(np.arange(a.size)//N)
Out[84]: array([ 71.33333333, 37.66666667, 57. , 37. ])
方法#2:基于平均值的切片和重塑
In [134]: limit0 = N*(a.size//N)
In [135]: out = np.zeros((a.size+N-1)//N)
In [136]: out[:limit0//N] = a[:limit0].reshape(-1,N).mean(1)
In [137]: out[limit0//N:] = a[limit0:].mean()
In [138]: out
Out[138]: array([ 71.33333333, 37.66666667, 57. , 37. ])
为了平滑数据,我建议使用基本上是卷积平均值的MATLAB's smooth
function ported to NumPy,并且应该与@Roman's post
类似。
答案 2 :(得分:0)
真的,真的希望numpy.ma.MaskedArray.resize有效。这将允许一步回答这个问题。
因为它是
def groupAverage(arr,idx):
rem=arr.size%idx
if rem==0:
return np.mean(arr.reshape(idx,-1),index=0)
else:
newsize=arr//size+1
averages=np.mean(arr.resize(idx,newsize),index=0)
averages[-1]*=(idx/rem)
return averages