usuwanie wierszy w tablicy numpy

88

Mam tablicę, która może wyglądać następująco:

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

Zwróć uwagę, że jeden z wierszy ma na końcu wartość zero. Chcę usunąć każdy wiersz zawierający zero, zachowując wiersz zawierający wartości niezerowe we wszystkich komórkach.

Ale tablica będzie miała różną liczbę wierszy za każdym razem, gdy zostanie zapełniona, a zera za każdym razem będą znajdować się w różnych wierszach.

Otrzymuję liczbę niezerowych elementów w każdym wierszu z następującym wierszem kodu:

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

Dla powyższej tablicy NumNonzeroElementsInRowszawiera: [5 4]

Pięć oznacza, że ​​wszystkie możliwe wartości w wierszu 0 są różne od zera, a cztery wskazują, że jedna z możliwych wartości w wierszu 1 to zero.

Dlatego próbuję użyć następujących wierszy kodu, aby znaleźć i usunąć wiersze zawierające wartości zerowe.

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

Ale z jakiegoś powodu ten kod nie wydaje się nic robić, nawet jeśli wykonanie wielu poleceń drukowania wskazuje, że wszystkie zmienne wydają się prawidłowo zapełniać, prowadząc do kodu.

Musi istnieć prosty sposób na „usunięcie dowolnego wiersza zawierającego wartość zerową”.

Czy ktoś może mi pokazać, jaki kod napisać, aby to osiągnąć?

MedicalMath
źródło

Odpowiedzi:

163

Najprostszym sposobem usunięcia wierszy i kolumn z tablic jest numpy.deletemetoda.

Załóżmy, że mam następującą tablicę x:

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

Aby usunąć pierwszy wiersz, wykonaj następujące czynności:

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

Aby usunąć trzecią kolumnę, wykonaj następujące czynności:

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

Możesz więc znaleźć indeksy wierszy, które mają w sobie 0, umieścić je na liście lub krotce i przekazać to jako drugi argument funkcji.

Jaidev Deshpande
źródło
Dzięki! Miałem ten sam problem i nie mogłem zrozumieć, dlaczego zwykłe dzwonienie numpy.delete(x, index)nie działa.
Antymon
6
zwróć uwagę, że dokumenty numpy delete () wskazują, że „Często lepiej jest użyć maski boolowskiej”, ponieważ zwracana jest nowa tablica - przykład znajduje się pod tym linkiem
arturomp
1
@arturomp, ale maska ​​jest bezpieczna. Czy wywołanie delete () zajmuje dużo czasu / pamięci?
Nathan
13

Oto jedna linijka (tak, jest podobna do user333700, ale trochę prostsza):

>>> 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]])

Nawiasem mówiąc, ta metoda jest dużo, dużo szybsza niż metoda maskowania dużych macierzy. W przypadku matrycy 2048 x 5 ta metoda jest około 1000x szybsza.

Nawiasem mówiąc, metoda user333700 (z jego komentarza) była nieco szybsza w moich testach, chociaż zastanawia mnie dlaczego.

Justin Peel
źródło
3
"dowolny" może spowodować zwarcie, gdy tylko zostanie wykryty pierwszy prawdziwy przypadek, może się zatrzymać, podczas gdy "wszystko" musi sprawdzić wszystkie warunki. Więc nie ("~" w numpy) żadne, generalnie powinno być szybsze niż wszystko.
Josef
4
@ user333700, oba mogą zwierać, tylko do różnych rzeczy. anyzwarcia do wartości true przy pierwszym wykrytym prawdziwym przypadku; allzwarcia do fałszu przy pierwszym wykrytym fałszywym przypadku. W tym przypadku zwarcie powinno być remisem, ale robienie extra nie powinno moim zdaniem spowalniać.
Justin Peel,
5

Jest to podobne do twojego pierwotnego podejścia i zajmie mniej miejsca niż odpowiedź unutbu , ale podejrzewam, że będzie wolniejsze.

>>> 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]])

Nawiasem mówiąc, twoja linia p.delete()nie działa dla mnie - ndarraynie mają .deleteatrybutu.

mtrw
źródło
8
trochę prostsze: p [~ (p == 0) .any (1)] lub bardziej wyraźne dla wierszy: p [~ (p == 0) .any (1),:]
Josef
2

numpy udostępnia prostą funkcję, która robi dokładnie to samo: zakładając, że masz zamaskowaną tablicę „a”, wywołanie numpy.ma.compress_rows (a) usunie wiersze zawierające zamaskowaną wartość. Myślę, że to jest znacznie szybsze w ten sposób ...

jepsy
źródło
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.)])
Prokhozhii
źródło
-1

Mogę być za późno, aby odpowiedzieć na to pytanie, ale chciałem podzielić się swoim wkładem dla dobra społeczności. W tym przykładzie nazwijmy twoją macierz „ANOVA” i zakładam, że próbujesz usunąć wiersze z tej macierzy z zerami tylko w piątej kolumnie.

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
źródło