避免使用NaN值并在python

时间:2018-06-01 11:27:29

标签: python numpy

我有两个4D矩阵,我想补充一下。矩阵具有完全相同的维度和元素数量,但它们都包含随机分布的NaN值。

我更愿意使用numpy.nansum将它们添加如下 (1)如果添加两个值,我希望总和为值,
(2)如果加上一个值和一个NaN,我希望总和为值和
(3)如果加入两个NaN,我希望总和为NaN。

此处我尝试了什么

a[6x7x180x360]
b[6x7x180x360]

C=np.nansum[(a,b)]
C=np.nansum(np.dstack((a,b)),2)

但是我无法得到与输入相同维度的结果矩阵。这意味着结果矩阵C应该在[6x7x180x360]中。 在这方面任何人都可以提供帮助提前谢谢。

3 个答案:

答案 0 :(得分:4)

您可以使用np.stack((a,b))沿新的0轴堆叠,然后调用nansum沿该0轴求和:

C = np.nansum(np.stack((a,b)), axis=0)

例如,

In [34]: a = np.random.choice([1,2,3,np.nan], size=(6,7,180,360))

In [35]: b = np.random.choice([1,2,3,np.nan], size=(6,7,180,360))

In [36]: np.stack((a,b)).shape
Out[36]: (2, 6, 7, 180, 360)

In [37]: np.nansum(np.stack((a,b)), axis=0).shape
Out[37]: (6, 7, 180, 360)

你有正确的想法,但np.dstack沿着第三轴堆叠,这是不可取的,因为你已经有4个轴:

In [31]: np.dstack((a,b)).shape
Out[31]: (6, 7, 360, 360)

关于你的观点(3): 请注意np.nansum depends on the NumPy version的行为:

  

在NumPy版本中< = 1.8.0,对于全NaN或切片,返回Nan   空。在以后的版本中,返回零。

如果您使用的是NumPy版本> 1.8.0,那么您可能必须使用solution such as Maarten Fabré's来解决此问题。

答案 1 :(得分:1)

我认为最简单的方法是使用np.where

result = np.where(
    np.isnan(a+b),
    np.where(np.isnan(a), b, a), 
    a+b
)

这读作: 如果a+b不是nan,请使用a+b,否则使用a,除非是nan,然后使用b。或者bnan是不是很重要。

或者,您可以像这样使用它:

result2 = np.where(
    np.isnan(a) & np.isnan(b),
    np.nan,
    np.nansum(np.stack((a,b)), axis=0)
)

np.testing.assert_equal(result, result2)通过

答案 2 :(得分:0)

我认为函数np.nansum不适合你的情况。如果我正确地理解了你的问题,你希望在元素方面添加两个矩阵,其中有一些关于NaN值的逻辑。

以下是有关如何操作的完整示例:

import numpy as np

a = np.array([  [np.nan, 2],
                [3, np.nan]])

b = np.array([  [3, np.nan],
                [1, np.nan]])

result = np.add(a,b)

a_is_nan = np.isnan(a)
b_is_nan = np.isnan(b)

result_is_nan = np.isnan(result)

mask_a = np.logical_and(result_is_nan, np.logical_not(a_is_nan))
result[mask_a] = a[mask_a]

mask_b = np.logical_and(result_is_nan, np.logical_not(b_is_nan))
result[mask_b] = b[mask_b]

print(result)

一点点解释:

第一个操作是np.add(a,b)。这会添加两个矩阵,任何NaN元素也会产生NaN的结果。

要从任一数组中选择NaN值,我们使用逻辑掩码:

# result_is_nan is a boolean array containing True whereve the result is np.NaN. This occurs when any of the two element were NaN
result_is_nan = np.isnan(result)

# mask_a is a boolean array which 'flags' elements that are NaN in result but were not NaN in a !
mask_a = np.logical_and(result_is_nan, np.logical_not(a_is_nan))
# Using that mask, we assign those value to result
result[mask_a] = a[mask_a]

你有它!