8

我想明智地添加数千个 4D 数组元素并考虑 nans。使用一维数组的简单示例是:

X = array([4,7,89,nan,89,65, nan])
Y = array([0,5,4, 9,  8, 100,nan])
z = X+Y
print z = array([4,12,93,9,97,165,nan])

我为此编写了一个简单的 for 循环,但它需要很长时间 - 这不是一个聪明的解决方案。另一种解决方案可能是创建一个更大的数组并使用bottleneck nansum,但这会占用我的笔记本电脑太多的内存。我需要超过 11000 个案例的总和。

有没有人有一个聪明而快速的方法来做到这一点?

4

5 回答 5

10

这是一种可能性:

>>> x = np.array([1, 2, np.nan, 3, np.nan, 4])
... y = np.array([1, np.nan, 2, 5, np.nan, 8])
>>> x = np.ma.masked_array(np.nan_to_num(x), mask=np.isnan(x) & np.isnan(y))
>>> y = np.ma.masked_array(np.nan_to_num(y), mask=x.mask)
>>> (x+y).filled(np.nan)
array([  2.,   2.,   2.,   8.,  nan,  12.])

真正的困难是您似乎希望nan被解释为零,除非特定位置的所有值都是nan. 这意味着您必须同时查看 x 和 y 以确定要替换的 nan。如果您可以替换所有 nan 值,那么您可以简单地执行np.nan_to_num(x) + np.nan_to_num(y).

于 2012-08-23T17:20:55.850 回答
3
import numpy as np
z=np.nansum([X,Y],axis=0)
于 2013-09-24T12:29:18.747 回答
3

您可以执行以下操作:

arr1 = np.array([1.0, 1.0, np.nan, 1.0, 1.0, np.nan])
arr2 = np.array([1.0, 1.0, 1.0, 1.0, 1.0, np.nan])
flags = np.isnan(arr1) & np.isnan(arr2)
copy1 = arr1.copy()
copy2 = arr2.copy()
copy1[np.isnan(copy1)] = 0.0
copy2[np.isnan(copy2)] = 0.0
out = copy1 + copy2
out[flags] = np.NaN
print out
array([  2.,   2.,   1.,   2.,   2.,  NaN])

NaN查找数组中在该索引中都有 a 的位置。然后,基本上按照@mgilson 的建议进行操作,例如制作副本并将NaNs 替换为 0.0,将两个数组相加,然后将上面的标记索引替换为np.NaN.

于 2012-08-23T17:23:28.843 回答
1

不知道这会如何执行,但值得一试:)

def nan_to_zero(array):
    new_arr = array.copy()
    new_arr[np.isnan(array)] = 0.
    return new_arr

sum( nan_to_zero(arr) for arr in array_generator )

但是,这不会导致NaN数组的最后一个位置。结果是0 ...

于 2012-08-23T17:12:12.553 回答
1

我看到了几个更简单的解决方案:

  • 已编辑)使用np.ma

    mX = np.ma.masked_array(X, mask=np.isnan(X))
    mY = np.ma.masked_array(Y, mask=np.isnan(Y))
    mZ = np.ma.masked_array(mX.filled(0) + mY.filled(0),
                            mask=mX.mask * mY.mask)
    Z = mZ.filled(np.nan)
    
  • 已编辑)不使用np.ma

    mx = np.isnan(x)
    my = np.isnan(y)
    z = np.where(mx,0,x) + np.where(my,0,y)
    z[mx&my] = np.nan
    
于 2012-08-24T20:42:42.663 回答