удаление пар элементов от массивов numpy, которые являются NaN (или другое значение) в Python

У меня есть массив с двумя столбцами в numpy. Например:

a = array([[1, 5, nan, 6],
           [10, 6, 6, nan]])
a = transpose(a)

Я хочу эффективно выполнить итерации через два столбца, [: 0] и [: 1] и удалите любых пар, которые соблюдают определенное условие, в этом случае если они - NaN. Очевидным путем я могу думать:

new_a = []
for val1, val2 in a:
  if val2 == nan or val2 == nan:
    new_a.append([val1, val2])

Но это кажется неуклюжим. Каков pythonic numpy способ сделать это?

спасибо.

11
задан 23 April 2010 в 00:49
поделиться

4 ответа

Если вы хотите взять только строки, у которых нет NAN, вам нужно это выражение:

>>> import numpy as np
>>> a[~np.isnan(a).any(1)]
array([[  1.,  10.],
       [  5.,   6.]])

Если вы хотите, чтобы строки не имели определенного числа среди его элементов, например 5:

>>> a[~(a == 5).any(1)]
array([[  1.,  10.],
       [ NaN,   6.],
       [  6.,  NaN]])

Последний явно эквивалентен

>>> a[(a != 5).all(1)]
array([[  1.,  10.],
       [ NaN,   6.],
       [  6.,  NaN]])

Explanation : Давайте сначала создадим ваш пример input

>>> import numpy as np
>>> a = np.array([[1, 5, np.nan, 6],
...               [10, 6, 6, np.nan]]).transpose()
>>> a
array([[  1.,  10.],
       [  5.,   6.],
       [ NaN,   6.],
       [  6.,  NaN]])

. Он определяет, какие элементы являются NAN.

>>> np.isnan(a)
array([[False, False],
       [False, False],
       [ True, False],
       [False,  True]], dtype=bool)

Это определяет, какие строки содержат какие-либо элементы, которые are True

>>> np.isnan(a).any(1)
array([False, False,  True,  True], dtype=bool)

Поскольку они нам не нужны, мы инвертируем последнее выражение:

>>> ~np.isnan(a).any(1)
array([ True,  True, False, False], dtype=bool)

И, наконец, мы используем логический массив для выбора нужных строк:

>>> a[~np.isnan(a).any(1)]
array([[  1.,  10.],
       [  5.,   6.]])
31
ответ дан 3 December 2019 в 01:33
поделиться

Я думаю, что понимание списка должно сделать это. Например,

new_a = [(val1, val2) for (val1, val2) in a if math.isnan(val1) or math.isnan(val2)]
2
ответ дан 3 December 2019 в 01:33
поделиться

Вы можете преобразовать массив в замаскированный массив и использовать метод compress_rows :

import numpy as np
a = np.array([[1, 5, np.nan, 6],
           [10, 6, 6, np.nan]])
a = np.transpose(a)
print(a)
# [[  1.  10.]
#  [  5.   6.]
#  [ NaN   6.]
#  [  6.  NaN]]
b=np.ma.compress_rows(np.ma.fix_invalid(a))
print(b)
# [[  1.  10.]
#  [  5.   6.]]
3
ответ дан 3 December 2019 в 01:33
поделиться

Не умалять ответ ig0774, который является совершенно правильным и питоническим и фактически является нормальным способом сделать эти вещи на простом Python, но: numpy поддерживает логическую систему индексирования, которая также может выполнять эту работу.

new_a = a[(a==a).all(1)]

Я не уверен, какой способ будет более эффективным (или более быстрым).

Если бы вы хотели использовать другое условие для выбора строк, это нужно было бы изменить, и это точно зависит от условия. Если это что-то, что можно оценить для каждого элемента массива независимо, вы можете просто заменить a == a соответствующим тестом, например, чтобы удалить все строки с числами больше 100, вы можете сделать

new_a = a[(a<=100).all(1)]

Но если вы пытаетесь сделать что-то необычное, включающее в себя все элементы в строке (например, удаление всех строк, сумма которых превышает 100), это может быть сложнее. Если это так, я могу попытаться отредактировать более конкретный ответ, если вы хотите поделиться своим точным состоянием.

3
ответ дан 3 December 2019 в 01:33
поделиться
Другие вопросы по тегам:

Похожие вопросы: