用最接近的非NaN值替换NumPy数组中的NaN

rob*_*ntw 19 python arrays numpy nan

我有一个NumPy数组a,如下所示:

>>> str(a)
'[        nan         nan         nan  1.44955726  1.44628034  1.44409573\n  1.4408188   1.43657094  1.43171624  1.42649744  1.42200684  1.42117704\n  1.42040255  1.41922908         nan         nan         nan         nan\n         nan         nan]'
Run Code Online (Sandbox Code Playgroud)

我想用最接近的非NaN值替换每个NaN,以便开头的1.449...所有NaN都被设置为并且最后的所有NaN都被设置为1.419....

我可以看到如何针对这样的特定情况执行此操作,但我需要能够对任何长度的数组执行此操作,在数组的开头和结尾处有任何长度的NaN(在该数组中没有NaN)中间的数字).有任何想法吗?

我可以很容易地找到NaN np.isnan(),但我无法弄清楚如何获得每个NaN最接近的值.

Joe*_*ton 39

作为替代解决方案(这将对NaN中间的数组进行线性插值):

import numpy as np

# Generate data...
data = np.random.random(10)
data[:2] = np.nan
data[-1] = np.nan
data[4:6] = np.nan

print data

# Fill in NaN's...
mask = np.isnan(data)
data[mask] = np.interp(np.flatnonzero(mask), np.flatnonzero(~mask), data[~mask])

print data
Run Code Online (Sandbox Code Playgroud)

这会产生:

[        nan         nan  0.31619306  0.25818765         nan         nan
  0.27410025  0.23347532  0.02418698         nan]

[ 0.31619306  0.31619306  0.31619306  0.25818765  0.26349185  0.26879605
  0.27410025  0.23347532  0.02418698  0.02418698]
Run Code Online (Sandbox Code Playgroud)

  • 真棒,我有一个很大的二维阵列,中间有一些麻烦的NaN,这使得平滑.谢谢. (4认同)
  • 这很有用,但它并没有做标题中的内容::“用最接近的非 NaN 值替换 NumPy 数组中的 NaN”。 (2认同)

NPE*_*NPE 21

我想用最接近的非NaN值替换每个NaN ...数字中间没有NaN

以下将这样做:

ind = np.where(~np.isnan(a))[0]
first, last = ind[0], ind[-1]
a[:first] = a[first]
a[last + 1:] = a[last]
Run Code Online (Sandbox Code Playgroud)

这是一个直接的numpy解决方案,不需要Python循环,没有递归,没有列表推导等.

  • @YonatanSimson 不,它没有,它戏剧性地失败,不知道为什么接受的解决方案 (3认同)
  • 如果其他人也有这种想法...是的,这对于没有NaN的数组是安全的,因为`a [:first]`将引用一个空切片,因为`first`将为0,而`a [last + 1: ]`将指向一个空片,因为`last + 1`将位于最后一个索引之后。分配给空片无效。为了防止代码不必要地运行,可以简单地使用`if np.any(np.isnan(a)):` (2认同)

Mat*_*lia 5

NaNs 有一个有趣的特性,就是比较不同自己,因此我们可以快速找到非 nan 元素的索引:

idx = np.nonzero(a==a)[0]
Run Code Online (Sandbox Code Playgroud)

现在很容易用所需的值替换 nans:

for i in range(0, idx[0]):
    a[i]=a[idx[0]]
for i in range(idx[-1]+1, a.size)
    a[i]=a[idx[-1]]
Run Code Online (Sandbox Code Playgroud)

最后,我们可以把它放在一个函数中:

import numpy as np

def FixNaNs(arr):
    if len(arr.shape)>1:
        raise Exception("Only 1D arrays are supported.")
    idxs=np.nonzero(arr==arr)[0]

    if len(idxs)==0:
        return None

    ret=arr

    for i in range(0, idxs[0]):
        ret[i]=ret[idxs[0]]

    for i in range(idxs[-1]+1, ret.size):
        ret[i]=ret[idxs[-1]]

    return ret
Run Code Online (Sandbox Code Playgroud)

编辑

哎哟,来自 C++ 我总是忘记列表范围......@aix 的解决方案比我的 C++ish 循环更优雅和高效,使用它而不是我的。