我需要比较一些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始终只有数字)。我可以想象已经有一个功能或东西,但我只是找不到它。
有什么想法吗?
答案 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))