видалення рядків у масиві numpy


89

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

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)

Але з якихось причин цей код, здається, нічого не робить, хоча виконання багатьох команд друку вказує на те, що всі змінні, здається, правильно заповнюються, ведучи до коду.

Повинен бути простий спосіб просто "видалити будь-який рядок, що містить нульове значення".

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

Відповіді:


164

Найпростішим способом видалення рядків і стовпців з масивів є 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)не спрацював.
Сурма

6
Зверніть увагу, що документи numpy delete () вказують, що "Часто переважно використовувати логічну маску", оскільки повертається новий масив - за цим посиланням наведено приклад
arturomp

1
@arturomp, але маска не руйнує. Виклик для видалення () забирає час / пам’ять?
Натан

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 х 5 цей метод приблизно в 1000 разів швидший.

До речі, метод user333700 (з його коментаря) був трохи швидшим у моїх тестах, хоча це мене бентежить.


3
"будь-який" може замикатися, як тільки виявляється перший справжній випадок, він може зупинитися, тоді як "всі" повинні перевірити всі умови. Отже, не ("~" в numpy) будь-який, загалом повинен бути швидшим за всі.
Йозеф

4
@ user333700, обидва вони можуть замикатися лише на різні речі. anyкоротке замикання на істину при першому виявленому справжньому випадку; allкоротке замикання на false при першому виявленому помилковому випадку. У цьому випадку коротке замикання має бути нічиєю, але зайве, на мою думку, не повинно зробити це повільнішим.
Джастін Піл,

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()у мене не працює - атрибути ndarrayне мають .delete.


8
дещо простіше: p [~ (p == 0) .any (1)] або більше явне для рядків: p [~ (p == 0) .any (1),:]
Йозеф

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]
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.