Мне нужно сравнить, равны ли два массива numpy желаемой точности, игнорируя значения nan.
Например:

a = [1,nan,3,nan]  
b = [1,0.2,3,4.1]  

Должен пройти тест.
Я пробовал использовать функцию numpy.all, но понимаю, что она ожидает, что два массива идентичны, и мне нужно иметь некоторую терпимость, потому что значения с плавающей запятой могут немного отличаться.
Как я могу этого добиться?

2
gustavo gonzalez 13 Мар 2018 в 02:28

2 ответа

Лучший ответ

Используйте np.allclose и np.isnan:

mask = ~(np.isnan(a) | np.isnan(b))
np.allclose(a[mask], b[mask])

Это правильно обрабатывает +/- inf и допускает небольшие различия. Абсолютные и относительные допуски могут быть указаны как параметры для allclose.

2
Paul Panzer 13 Мар 2018 в 02:37

Целочисленные массивы
Замаскируйте свои массивы с помощью np.isfinite и сравните с np.array_equal:

def array_nan_equal(a, b):
    m = np.isfinite(a) & np.isfinite(b)
    return np.array_equal(a[m], b[m])
assert array_nan_equal(
     np.array([1, np.nan, 3, np.nan]), np.array([1, 2, 3, 4])
)
assert not array_nan_equal(
     np.array([1, 4, 3, np.nan]), np.array([1, 2, 3, 4])
)

Обратите внимание, что если вы хотите учитывать +/- inf, вы можете следовать подсказке в ответе @Paul Panzer и использовать m = ~(np.isnan(a) & np.isnan(b)) вместо np.isfinite.


Массивы с плавающей запятой
Для чисел с плавающей запятой вам нужно будет сравнить в пределах допуска, поэтому замените np.array_equal вызовом np.allclose:

def array_nan_close(a, b):
    m = np.isfinite(a) & np.isfinite(b)
    return np.allclose(a[m], b[m])
assert array_nan_close(
     np.array([1.3, np.nan, 3.4, np.nan]), np.array([1.3000001, 2, 3.4, 4])
)
assert not array_nan_close(
     np.array([1.1, 4.0, 3.5, np.nan]), np.array([1, 2, 3, 4])
)
1
cs95 13 Мар 2018 в 12:02