У меня есть массив с двумя столбцами в 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 способ сделать это?
спасибо.
Если вы хотите взять только строки, у которых нет 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.]])
Я думаю, что понимание списка должно сделать это. Например,
new_a = [(val1, val2) for (val1, val2) in a if math.isnan(val1) or math.isnan(val2)]
Вы можете преобразовать массив в замаскированный массив и использовать метод 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.]]
Не умалять ответ ig0774, который является совершенно правильным и питоническим и фактически является нормальным способом сделать эти вещи на простом Python, но: numpy поддерживает логическую систему индексирования, которая также может выполнять эту работу.
new_a = a[(a==a).all(1)]
Я не уверен, какой способ будет более эффективным (или более быстрым).
Если бы вы хотели использовать другое условие для выбора строк, это нужно было бы изменить, и это точно зависит от условия. Если это что-то, что можно оценить для каждого элемента массива независимо, вы можете просто заменить a == a
соответствующим тестом, например, чтобы удалить все строки с числами больше 100, вы можете сделать
new_a = a[(a<=100).all(1)]
Но если вы пытаетесь сделать что-то необычное, включающее в себя все элементы в строке (например, удаление всех строк, сумма которых превышает 100), это может быть сложнее. Если это так, я могу попытаться отредактировать более конкретный ответ, если вы хотите поделиться своим точным состоянием.