如何比较两个numpy数组与一些NaN值?

时间:2017-01-28 20:00:06

标签: python arrays python-3.x numpy compare

我需要比较一些numpy数组,它们应该以相同的顺序具有相同的元素,除了第二个中的一些NaN值。

我需要一个或多或少的功能:

def func( array1, array2 ):
    if ???:
        return True
    else:
        return False

示例:

x = np.array( [ 1, 2, 3, 4, 5 ] )
y = np.array( [ 11, 2, 3, 4, 5 ] )
z = np.array( [ 1, 2, np.nan, 4, 5] )

func( x, z ) # returns True
func( y, z ) # returns False

数组的长度始终相同,NaN值始终位于第三个(x和y始终只有数字)。我可以想象已经有一个功能或东西,但我只是找不到它。

有什么想法吗?

3 个答案:

答案 0 :(得分:5)

你可以使用蒙面数组,当你与np.all结合使用时,它会有你要求的行为:

zm = np.ma.masked_where(np.isnan(z), z)

np.all(x == zm) # returns True
np.all(y == zm) # returns False

或者您可以明确地写出您的逻辑,注意numpy必须使用|而不是or,并且结果会导致运算符优先级的差异:

def func(a, b):
    return np.all((a == b) | np.isnan(a) | np.isnan(b))

答案 1 :(得分:2)

您可以使用isclose检查是否相等(或接近给定的容差 - 这在比较浮点数时特别有用)并使用isnan检查第二个数组中的NaN。 使用按位或(|)组合两者,并使用all要求每对都关闭或包含NaN以获得所需结果:

In [62]: np.isclose(x,z)
Out[62]: array([ True,  True, False,  True,  True], dtype=bool)

In [63]: np.isnan(z)
Out[63]: array([False, False,  True, False, False], dtype=bool)

所以你可以使用:

def func(a, b):
    return (np.isclose(a, b) | np.isnan(b)).all()


In [67]: func(x, z)
Out[67]: True

In [68]: func(y, z)
Out[68]: False

答案 2 :(得分:0)

怎么样:

from math import isnan

def fun(array1,array2):
    return all(isnan(x) or isnan(y) or x == y for x,y in zip(array1,array2))

此功能适用于两个方向(如果第一个列表中有NaN个,则这些也会被忽略)。如果你不想那样(这有点奇怪,因为相等通常是双向的)。您可以定义:

from math import isnan

def fun(array1,array2):
    return all(isnan(y) or x == y for x,y in zip(array1,array2))

代码的工作原理如下:我们使用zip来发出两个数组元素的元组。接下来,我们检查第一个列表的元素是NaN,还是第二个,或者它们是相等的。

鉴于你想要写一个非常优雅的功能,你最好还要进行长度检查:

from math import isnan

def fun(array1,array2):
    return len(array1) == len(array2) and all(isnan(y) or x == y for x,y in zip(array1,array2))