微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

计算二维Numpy数组的行移动平均值时处理np.NaN

如何解决计算二维Numpy数组的行移动平均值时处理np.NaN

我正在尝试基于某个“窗口”(即平均值中包含的行数)来获得一个包含沿二维numpy数组的行移动的平均值的数组 )和“偏移”。我想出了下面的代码,我知道这是无效的:

import numpy as np
def f(array,window,offset):
    x = np.empty(array.shape)
    x[:,:] = np.NaN
    for row_num in range(array.shape[0]):
        first_row = row_num - window - offset
        last_row = row_num - offset + 1
        if first_row >= 0:
            x[row_num] = np.nanmean(array[first_row:last_row],axis=0)
    return x

我找到了一种可能的解决方here,下面针对我的代码进行了修改

import math
from scipy.ndimage import uniform_filter
def g(array,offset):
    return uniform_filter(array,size=(window+1,1),mode='nearest',origin=(math.ceil((window+1)/2-1),0))

但是,此解决方案存在3个问题:

  • 首先,我不确定如何实现“偏移”
  • 第二,我不确定它是否确实更有效
  • 第三,也是最重要的是,当输入数组包含np.nan 时,它不起作用。找到np.nan的那一刻,它就会在移动平均线中向下拖动,而不是跟随np.nanmean行为。

有没有一种有效的方法来实现我想要的目标?

更新

按照埃桑(Ehsan)的建议,我已经实现了以下代码(稍作修改),该代码可作为我的原始代码来处理大于0的任何偏移量:

from skimage.util import view_as_windows
def h(array,offset):
    return np.vstack(([[np.NaN]*array.shape[-1]]*(window+offset),np.vstack(np.nanmean(view_as_windows(array,(window+1,array.shape[-1])),-2)[:-offset])))

我只是不确定如何使它适用于任何偏移量(尤其是offset = 0)。而且,此解决方案似乎比原始解决方案消耗更多时间:

a = np.arange(10*11).reshape(10,11)

%timeit f(a,5,2)
%timeit h(a,2)
>>> 36.6 µs ± 709 ns per loop (mean ± std. dev. of 7 runs,10000 loops each)
>>> 67.5 µs ± 2.34 µs per loop (mean ± std. dev. of 7 runs,10000 loops each)

我想知道是否还有其他方法可以节省时间

解决方法

这将为您提供与代码相同的输出,但是我认为您可能需要重新考虑+1定义中的额外last_row,因为它会跳过最后一行,并且实际的窗口大小为窗口+1:

from skimage.util import view_as_windows
def f(array,window,offset):
    return np.vstack(([[np.NaN]*array.shape[-1]]*(window+offset),np.vstack(np.nanmean(view_as_windows(array,(window+1,array.shape[-1])),-2)[:array.shape[0]-window-offset])))

示例输出:

a = np.arange(7*6).reshape(7,6)
f(a,2,1)
#[[nan nan nan nan nan nan]
# [nan nan nan nan nan nan]
# [nan nan nan nan nan nan]
# [ 6.  7.  8.  9. 10. 11.]
# [12. 13. 14. 15. 16. 17.]
# [18. 19. 20. 21. 22. 23.]
# [24. 25. 26. 27. 28. 29.]]

比较,使用benchit

#@OP's solution
def f1(array,offset):
    x = np.empty(array.shape)
    x[:,:] = np.NaN
    for row_num in range(array.shape[0]):
        first_row = row_num - window - offset
        last_row = row_num - offset + 1
        if first_row >= 0:
            x[row_num] = np.nanmean(array[first_row:last_row],axis=0)
    return x
#@Ehsan's solution
def f2(array,-2)[:array.shape[0]-window-offset])))

in_ = {n:[np.arange(n*10).reshape(n,10),2] for n in [10,100,500,1000,4000]}

建议的解决方案 f2 明显更快。您必须注意,大多数矢量化解决方案在较大的阵列上都是有效的。

enter image description here

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。