关注How exactly does the “reflect” mode for scipys ndimage filters work?和Numpy Two-Dimensional Moving Average,我有一个二维数组:
a
=>
np.array([[ 0., 1., 2., 3., 4.],
[ 5., 6., 7., 8., 9.],
[ 10., 11., 12., 13., 14.],
[ 15., 16., 17., 18., 19.],
[ 20., 21., 22., 23., 24.]])
当我使用mode=constant
和3x3 filter size
:
uniform_filter(a, size=3, mode='constant')
结果是:
=>
array([[ 1.33333333, 2.33333333, 3. , 3.66666667, 2.66666667],
[ 3.66666667, 6. , 7. , 8. , 5.66666667],
[ 7. , 11. , 12. , 13. , 9. ],
[ 10.33333333, 16. , 17. , 18. , 12.33333333],
[ 8. , 12.33333333, 13. , 13.66666667, 9.33333333]])
我理解这个过滤器是如何在内部工作的,因为我在上面发布的链接中对它进行了很好的解释。
我的问题是,对于数组中的每个位置,是否可以将其总和除以其值大于零的元素总数?
例如,在我的数组中位置[0,0],其中元素为0
,元素(0, 0, 0, 0, 0, 1, 0, 5, 6)
的总和将除以3
(仅位置[ 0,1] = 1
,[1,0] = 5
和[1,1] = 6
的值大于零)而不是9
。在数组的位置[0,1],我将除以5
。在位置[0,2]中,我除以6
并且在位置[1,2]中除以9
。
在这种情况下,我的答案应该是;
=>
array([[ 4.0 , 4.2 , 4.5 , 5.5 , 6.0 ],
[ 6.60, 6.75, 7.0 , 8.0 , 8.5 ],
[ 10.5, 11. , 12. , 13. , 13.5 ],
[ 15.5, 16. , 17. , 18. , 18.5 ],
[ 18.0, 18.5, 19.5, 20.5, 21.0 ]])
答案 0 :(得分:2)
这是一种方法 -
from scipy.ndimage.filters import uniform_filter
from scipy.signal import convolve2d
size = 3
kernel = np.ones((size,size),dtype=int)
nonzero_count = convolve2d(a!=0, kernel,'same')
windowed_sum = uniform_filter(a, size=size, mode='constant')*size**2
out = windowed_sum/nonzero_count
步骤:
沿着输入数组的行和列,在形状:(size,size)
的滑动窗口中计算非零数。
为此,我们可以使用2D
卷积与所有ones
的内核以及与内核相同的形状。或者,我们也可以使用uniform_filter
获取非零计数:uniform_filter((a!=0).astype(float), size=size, mode='constant')*size**2
。
通过重复使用uniform_filter
输出的平均值并按size**2
缩放来获取滑动求和。或者,我们可以使用2D
再次使用convolve2d(a, kernel,'same')
卷积。
最后,将这些求和除以非零计数,这是期望的输出。
样本输入,中间输出和最终输出 -
In [51]: a
Out[51]:
array([[ 0., 1., 2., 3., 4.],
[ 5., 6., 7., 8., 9.],
[ 10., 11., 12., 13., 14.],
[ 15., 16., 17., 18., 19.],
[ 20., 21., 22., 23., 24.]])
In [53]: nonzero_count
Out[53]:
array([[3, 5, 6, 6, 4],
[5, 8, 9, 9, 6],
[6, 9, 9, 9, 6],
[6, 9, 9, 9, 6],
[4, 6, 6, 6, 4]])
In [54]: windowed_sum
Out[54]:
array([[ 12., 21., 27., 33., 24.],
[ 33., 54., 63., 72., 51.],
[ 63., 99., 108., 117., 81.],
[ 93., 144., 153., 162., 111.],
[ 72., 111., 117., 123., 84.]])
In [55]: out
Out[55]:
array([[ 4. , 4.2 , 4.5 , 5.5 , 6. ],
[ 6.6 , 6.75, 7. , 8. , 8.5 ],
[ 10.5 , 11. , 12. , 13. , 13.5 ],
[ 15.5 , 16. , 17. , 18. , 18.5 ],
[ 18. , 18.5 , 19.5 , 20.5 , 21. ]])