我有两个5D矩阵,我想添加元素。矩阵具有完全相同的维数和元素数,但它们都包含随机分布的NaN值。
我想以有效的方式逐个元素地添加这两个矩阵。我目前通过元素循环遍历它们来添加它们,但是这个循环大约需要40分钟,我只是认为必须有一种更有效的方法。
我认为这是一种有效的方法,如果可以使用numpy.nansum来添加它们,但是根据我的发现,numpy.nansum仅适用于1D数组。
如果添加功能与numpy.nansum(https://docs.scipy.org/doc/numpy-1.13.0/reference/generated/numpy.nansum.html)相同,我会更喜欢它。即,(1)如果添加两个值,我希望总和为值,(2)如果添加值和NaN,我希望总和为值,(3)如果添加两个NaN,我想要总和为NaN。
以下是一个支付代码:
import numpy as np
# Creating fake data
A = np.arange(0,720,1).reshape(2,3,4,5,6)
B = np.arange(720,1440,1).reshape(2,3,4,5,6)
# Assigning some elements as NaN
A[0,1,2,3,4] = np.nan
A[1,2,3,4,5] = np.nan
B[1,2,3,4,5] = np.nan
所以,如果我现在添加A和B(假设C = A + B),我希望元素C [0,1,2,3,4]为B [0,1,2的值, 3,4],元素C [1,2,3,4,5]为NaN,C中的所有其他元素为A和B中各元素的总和。
有没有人有这种添加的有效解决方案?
答案 0 :(得分:2)
我在想一些更平淡无奇的东西
In [22]: A=np.arange(10.) # make sure A is float
In [23]: B=np.arange(100,110.)
In [24]: A[[1,3,9]]=np.nan
In [25]: B[[2,5,9]]=np.nan
In [26]: A
Out[26]: array([ 0., nan, 2., nan, 4., 5., 6., 7., 8., nan])
In [27]: B
Out[27]: array([100., 101., nan, 103., 104., nan, 106., 107., 108., nan])
In [29]: C=A+B
In [30]: C
Out[30]: array([100., nan, nan, nan, 108., nan, 112., 114., 116., nan])
In [31]: mask1 = np.isnan(A) & ~np.isnan(B)
In [32]: C[mask1] = B[mask1]
In [33]: mask2 = np.isnan(B) & ~np.isnan(A)
In [34]: C[mask2] = A[mask2]
In [35]: C
Out[35]: array([100., 101., 2., 103., 108., 5., 112., 114., 116., nan])
我喜欢stack
和nansum
方法,但我不确定它是否更快:
In [36]: s=np.stack((A,B))
In [37]: C1 = np.nansum(s, axis=0)
In [38]: C1
Out[38]: array([100., 101., 2., 103., 108., 5., 112., 114., 116., 0.])
In [40]: C1[np.all(np.isnan(s), axis=0)] = np.nan
In [41]: C1
Out[41]: array([100., 101., 2., 103., 108., 5., 112., 114., 116., nan])
如果这种方法令人费解,请看s
:
In [42]: s
Out[42]:
array([[ 0., nan, 2., nan, 4., 5., 6., 7., 8., nan],
[100., 101., nan, 103., 104., nan, 106., 107., 108., nan]])
s
是一个新的数组,具有新的0维。该维度上的sum
与A+B
相同。这种堆叠让我们可以利用nansum
。不幸的是,您仍然希望保留一些nan
,因此我们仍然需要执行屏蔽分配来处理该细节。
答案 1 :(得分:2)
np.where(np.isnan(A), B, A + np.nan_to_num(B))
我们看到它如何在两个部分中起作用:
A
的南部,我们填写B
的值。 如果B
和A
同时为nan
,则存储的值将为nan
。如果B
不是nan
而A
是nan
,则会存储B
的值。
A
部分,我们填写A + np.nan_to_num(B)
。 np.nan_to_num(B)
会将B
的nan部分变为0.因此,当A + np.nan_to_num(B)
为nan
时,B
将不会nan
。
感谢Paul Panzer的纠正。
答案 2 :(得分:1)
在求和之前添加一把新斧头:
np.nansum(np.concatenate((A[None,:],B[None,:])),axis=0)
答案 3 :(得分:1)
s = np.stack((A, B))
C = np.nansum(s, axis=0)
C[np.all(np.isnan(s), axis=0)] = np.nan
这会将np.nan
视为0.0
以进行求和,然后最后一行会为新的"深度&#中的所有条目添加np.nan
所存在的位置34;横跨A
和B
的轴。
请注意,NumPy版本需要最后一次操作> 1.8,如the documentation中所述:
在NumPy版本中< = 1.8.0,对于全NaN或空的切片,返回Nan。在以后的版本中,返回零。
如果你可以保证NumPy版本< = 1.8,那么仅仅nansum
部分就足够了。