удаление строк в массиве numpy

88

У меня есть массив, который может выглядеть так:

ANOVAInputMatrixValuesArray = [[ 0.96488889, 0.73641667, 0.67521429, 0.592875, 
0.53172222], [ 0.78008333, 0.5938125, 0.481, 0.39883333, 0.]]

Обратите внимание, что одна из строк имеет нулевое значение в конце. Я хочу удалить любую строку, содержащую ноль, сохранив при этом любую строку, содержащую ненулевые значения во всех ячейках.

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

Я получаю количество ненулевых элементов в каждой строке с помощью следующей строки кода:

NumNonzeroElementsInRows    = (ANOVAInputMatrixValuesArray != 0).sum(1)

Для указанного выше массива NumNonzeroElementsInRowsсодержит: [5 4]

Пять указывает, что все возможные значения в строке 0 отличны от нуля, а четыре указывает, что одно из возможных значений в строке 1 равно нулю.

Поэтому я пытаюсь использовать следующие строки кода для поиска и удаления строк, содержащих нулевые значения.

for q in range(len(NumNonzeroElementsInRows)):
    if NumNonzeroElementsInRows[q] < NumNonzeroElementsInRows.max():
        p.delete(ANOVAInputMatrixValuesArray, q, axis=0)

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

Должен быть какой-то простой способ просто «удалить любую строку, содержащую нулевое значение».

Может ли кто-нибудь показать мне, какой код написать для этого?

Медицинская математика
источник

Ответы:

163

Самый простой способ удалить строки и столбцы из массивов - это numpy.deleteметод.

Предположим, у меня есть следующий массив x:

x = array([[1,2,3],
        [4,5,6],
        [7,8,9]])

Чтобы удалить первую строку, сделайте следующее:

x = numpy.delete(x, (0), axis=0)

Чтобы удалить третий столбец, сделайте следующее:

x = numpy.delete(x,(2), axis=1)

Таким образом, вы можете найти индексы строк, в которых есть 0, поместить их в список или кортеж и передать это как второй аргумент функции.

Джайдев Дешпанде
источник
Благодарность! У меня была такая же проблема, и я не мог понять, почему просто позвонить numpy.delete(x, index)не удалось.
Antimony
6
обратите внимание, что в документации numpy delete () указано, что «Часто предпочтительнее использовать логическую маску», поскольку возвращается новый массив - пример предоставлен по этой ссылке
arturomp
1
@arturomp, но маска неразрушающая. Требуется ли время / память при вызове функции delete ()?
Nathan
13

Вот один лайнер (да, он похож на user333700, но немного проще):

>>> import numpy as np
>>> arr = np.array([[ 0.96488889, 0.73641667, 0.67521429, 0.592875, 0.53172222], 
                [ 0.78008333, 0.5938125, 0.481, 0.39883333, 0.]])
>>> print arr[arr.all(1)]
array([[ 0.96488889,  0.73641667,  0.67521429,  0.592875  ,  0.53172222]])

Кстати, этот метод намного, намного быстрее, чем метод маскированного массива для больших матриц. Для матрицы 2048 x 5 этот метод примерно в 1000 раз быстрее.

Кстати, метод user333700 (из его комментария) был немного быстрее в моих тестах, хотя я не понимаю, почему.

Джастин Пил
источник
3
«Любой» может закоротить, как только обнаружен первый истинный случай, он может остановиться, а «все» должны проверить все условия. Итак, not ("~" в numpy) любой, вообще должен быть быстрее всех.
Josef
4
@ user333700, оба они могут закоротить, просто на разные вещи. anyзамыкание на истину при первом обнаруженном истинном случае; allкороткое замыкание на ложь при первом обнаруженном ложном случае. В этом случае короткое замыкание должно быть ничьей, но, на мой взгляд, дополнительные действия не должны замедлить его.
Джастин Пил,
5

Это похоже на ваш исходный подход и будет занимать меньше места, чем ответ unutbu , но я подозреваю, что он будет медленнее.

>>> import numpy as np
>>> p = np.array([[1.5, 0], [1.4,1.5], [1.6, 0], [1.7, 1.8]])
>>> p
array([[ 1.5,  0. ],
       [ 1.4,  1.5],
       [ 1.6,  0. ],
       [ 1.7,  1.8]])
>>> nz = (p == 0).sum(1)
>>> q = p[nz == 0, :]
>>> q
array([[ 1.4,  1.5],
       [ 1.7,  1.8]])

Кстати, ваша линия p.delete()не работает для меня - ndarrays не имеет .deleteатрибута.

mtrw
источник
8
немного проще: p [~ (p == 0) .any (1)] или более явно для строк: p [~ (p == 0) .any (1),:]
Josef
2

numpy предоставляет простую функцию, которая делает то же самое: предположим, что у вас есть замаскированный массив 'a', вызов numpy.ma.compress_rows (a) удалит строки, содержащие замаскированное значение. Я думаю, это намного быстрее ...

джипы
источник
1
import numpy as np 
arr = np.array([[ 0.96488889, 0.73641667, 0.67521429, 0.592875, 0.53172222],[ 0.78008333, 0.5938125, 0.481, 0.39883333, 0.]])
print(arr[np.where(arr != 0.)])
Прохожий
источник
-1

Я мог бы слишком поздно ответить на этот вопрос, но хотел поделиться своим мнением на благо сообщества. В этом примере позвольте мне назвать вашу матрицу «ANOVA», и я предполагаю, что вы просто пытаетесь удалить строки из этой матрицы с нулями только в 5-м столбце.

indx = []
for i in range(len(ANOVA)):
    if int(ANOVA[i,4]) == int(0):
        indx.append(i)

ANOVA = [x for x in ANOVA if not x in indx]
troymyname00
источник