Python 在一维numpy数组中计算局部均值
我有如下一维NumPy阵列:Python 在一维numpy数组中计算局部均值,python,arrays,numpy,scipy,mean,Python,Arrays,Numpy,Scipy,Mean,我有如下一维NumPy阵列: import numpy as np d = np.array([1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20]) 我想计算(1,2,6,7),(3,4,8,9)的平均值,依此类推。 这涉及4个元素的平均值:两个连续元素和两个连续元素5个位置后的平均值 我尝试了以下方法: >> import scipy.ndimage.filters as filt >> res = filt.uni
import numpy as np
d = np.array([1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20])
我想计算(1,2,6,7),(3,4,8,9)的平均值,依此类推。
这涉及4个元素的平均值:两个连续元素和两个连续元素5个位置后的平均值
我尝试了以下方法:
>> import scipy.ndimage.filters as filt
>> res = filt.uniform_filter(d,size=4)
>> print res
[ 1 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19]
不幸的是,这并没有给我期望的结果。我该怎么做呢?您可以从信号处理的角度来处理这个问题,而不是索引。基本上,您是在使用7-tap内核执行输入信号的计算,其中三个中心系数为0,而极值为1,并且由于您要计算平均值,因此需要将所有值乘以
(1/4)
。然而,您并没有计算所有元素的卷积,但我们将在稍后讨论。
一种方法是使用:
import numpy as np
from scipy.ndimage import filters
d = np.arange(1, 21, dtype=np.float)
ker = (1.0/4.0)*np.array([1,1,0,0,0,1,1], dtype=np.float)
out = filters.convolve1d(d, ker)[3:-3:2]
因为您使用的是7抽头内核,卷积会将输出向左扩展3,向右扩展3,所以您需要确保裁剪出第一个和最后三个元素。由于卷积涉及一个滑动窗口,因此您还希望跳过其他所有元素,但您希望放弃所有其他元素,以便获得所需的结果
我们为输出:
In [47]: out
Out[47]: array([ 4., 6., 8., 10., 12., 14., 16.])
要仔细检查结果是否正确,请尝试对每个元素进行一些示例计算。第一个元素等于(1+2+6+7)/4=4
。第二个元素等于(3+4+8+9)/4=6
,依此类推
要想解决问题,请尝试使用mode=valid
标志。这样可以避免在左右两侧剪切额外的填充,但仍然需要跳过其他元素:
import numpy as np
d = np.arange(1, 21, dtype=np.float)
ker = (1.0/4.0)*np.array([1,1,0,0,0,1,1], dtype=np.float)
out = np.convolve(d, ker, mode='valid')[::2]
我们还得到:
In [59]: out
Out[59]: array([ 4., 6., 8., 10., 12., 14., 16.])
最后,如果您想要建立索引,这样做就足够了:
length = len(d[6::2])
out = np.array([(a+b+c+e)/4.0 for (a,b,c,e) in zip(d[::2][:length], d[1::2][:length], d[5::2][:length], d[6::2])])
我们得到:
In [69]: out
Out[69]: array([ 4., 6., 8., 10., 12., 14., 16.])
这真的很难看,但它是有效的。信号的总长度取决于每个窗口的末尾位于第7个索引。包含这些索引的数组的长度决定了信号的最终长度。另外,请注意,对于窗口中的一个元素,可以通过跳过每个其他元素直到数组结束来找到它的下一个元素。总共有4个这样的序列,我们只需对这4个序列进行zip
,其中每个序列跳过其他元素,但有一个偏移量,我们从开始。第一个序列从偏移量0开始,下一个序列从1开始,下一个序列从5开始,下一个序列从6开始。我们收集这四个元素并求平均值,然后跳过数组中的每一个元素,直到完成为止
顺便说一句,我仍然更喜欢卷积。您可以使用numpy.lib.stride\u技巧。as\u stride()
获得适用于更一般情况的分组数组:
import numpy as np
from numpy.lib.stride_tricks import as_strided
d = np.arange(1, 21)
consec = 2
offset = 5
nsub = 2
pace = 2
s = d.strides[0]
ngroups= (d.shape[0] - (consec + (nsub-1)*offset - 1))//pace
a = as_strided(d, shape=(ngroups, nsub, consec),
strides=(pace*s, offset*s, 1*s))
其中:
conce
是子组中的连续数
offset
每个子组中第一个条目之间的偏移量
nsub
子组的数量(1,2
是一个子组,与第二个子组6,7
通过offset
pace
表示两组中第一个条目之间的步幅,在您的情况下为pace=concer
,但在更一般的情况下可能不同
在您的情况下(使用给定值)a
将是:
array([[[ 1, 2],
[ 6, 7]],
[[ 3, 4],
[ 8, 9]],
[[ 5, 6],
[10, 11]],
[[ 7, 8],
[12, 13]],
[[ 9, 10],
[14, 15]],
[[11, 12],
[16, 17]],
[[13, 14],
[18, 19]]])
通过以下操作,即可获得所需的平均值:
a.mean(axis=-1).mean(axis=-1)
#array([ 4., 6., 8., 10., 12., 14., 16.])
你是如何选择那些数字1、2、6、7的?规则是什么?@omri_saadon两个连续的元素,在5个元素之后是另外两个连续的元素。我可以看到你在这里插入了数据,可能是图像数据。为什么不重新表述这个问题,以便清楚这两个集合中的每一个都需要哪个序列?@gburton好的,我这样做了it@Borys-N问题。我有正确的答案,但删除了我的帖子,因为我不确定我是否做对了…但现在我知道我做对了!看一看。非常酷的把戏…让我更爱Nuv numpy每一天我离开MATLAB。我喜欢这种复杂但很高兴看到…评论不是用于扩展讨论的;这段对话已经结束。