Jak usunąć określone elementy z tablicy numpy


212

Jak mogę usunąć niektóre określone elementy z tablicy numpy? Powiedz, że mam

import numpy as np

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

Następnie chcę usunąć 3,4,7z a. Wiem tylko indeks wartości ( index=[2,3,6]).

Odpowiedzi:


285

Użyj numpy.delete () - zwraca nową tablicę z usuniętymi pod-tablicami wzdłuż usuniętej osi

numpy.delete(a, index)

W przypadku konkretnego pytania:

import numpy as np

a = np.array([1, 2, 3, 4, 5, 6, 7, 8, 9])
index = [2, 3, 6]

new_a = np.delete(a, index)

print(new_a) #Prints `[1, 2, 5, 6, 8, 9]`

Zauważ, że numpy.delete()zwraca nową tablicę, ponieważ skalary tablic są niezmienne, podobnie jak łańcuchy w Pythonie, więc za każdym razem, gdy wprowadzana jest do niej zmiana, tworzony jest nowy obiekt. Cytując delete() dokumenty :

Kopia arr z usuniętymi elementami określonymi przez obj. Pamiętaj, że usuwanie nie występuje w miejscu ...”

Jeśli kod, który publikuję, ma wynik, jest to wynikiem uruchomienia kodu.


1
@IngviGautsson Kiedy dokonałeś edycji, zmieniłeś również prawidłowe wartości elementów z 2, 3, 6 na 3, 4, 7, jeśli uruchomisz kod teraz, nie uzyskasz prawidłowego wyjścia, jak to było pierwotnie. „Cofam edycję
Levon

1
AttributeError: obiekt „list” nie ma atrybutu „delete”
munmunbb

3
@IngviGautsson Nie, twój komentarz wprowadza w błąd. Działa to zgodnie z oczekiwaniami. Jednak dokumentacja numpy.delete () zauważa, że ​​„często lepiej jest używać maski logicznej”; podany jest również przykład.
Biggsy,

1
@Levon, czy możesz dodać przykłady 2D?
MattS

7
@IngviGautsson Mylisz się. Usuwa indeksy elementów, a nie same elementy.
Le Frite

64

Pomaga w tym wbudowana funkcja numpy.

import numpy as np
>>> a = np.array([1, 2, 3, 4, 5, 6, 7, 8, 9])
>>> b = np.array([3,4,7])
>>> c = np.setdiff1d(a,b)
>>> c
array([1, 2, 5, 6, 8, 9])

7
Dobrze wiedzieć. Myślałem, że np.delete będzie wolniejszy, ale niestety, czas na 1000 liczb całkowitych mówi, że usuwanie jest x2 szybsze.
wbg

1
To jest wielki, ponieważ działa na macierzy za wartościami zamiast dostarczyć indeksy index /, które chcesz usunąć. Na przykład:np.setdiff1d(np.array(['one','two']),np.array(['two', 'three']))
MD004

To również sortuje dane wyjściowe, co może nie być tym, czego chce. W przeciwnym razie bardzo miło.
rayzinnz

Pytanie brzmi: „Wszystko, co wiem, to indeks wartości”. Chodzi więc o usuwanie przedmiotów według ich indeksów , a nie usuwanie ich wartościami
Sherzod

35

Tablica Numpy jest niezmienna , co oznacza, że ​​technicznie nie można usunąć z niej elementu. Możesz jednak zbudować nową tablicę bez wartości, których nie chcesz:

b = np.delete(a, [2,3,6])

1
+1 za wzmiankę o „niezmiennym”. Warto pamiętać, że tablice numpy nie nadają się do szybkich zmian wielkości (dodawanie / usuwanie elementów)
eumiro,

38
technicznie, tablice numpy SĄ mutable. Na przykład: a[0]=1modyfikuje aw miejscu. Ale nie można zmienić ich rozmiaru.
btel

3
Definicja mówi, że jest niezmienna, ale jeśli przypisując nową wartość pozwala ci to modyfikować, to jak ją niezmienną?
JSR

16

Aby usunąć według wartości:

modified_array = np.delete(original_array, np.where(original_array == value_to_delete))

Pytanie dotyczy usuwania przedmiotów według indeksów , a nie usuwania przedmiotów o określonej wartości
Sherzod

5

Nie będąc odrętwioną osobą, zrobiłem zdjęcie z:

>>> import numpy as np
>>> import itertools
>>> 
>>> a = np.array([1,2,3,4,5,6,7,8,9])
>>> index=[2,3,6]
>>> a = np.array(list(itertools.compress(a, [i not in index for i in range(len(a))])))
>>> a
array([1, 2, 5, 6, 8, 9])

Według moich testów osiąga to lepsze wyniki numpy.delete(). Nie wiem, dlaczego tak się dzieje, może z powodu małego rozmiaru początkowej tablicy?

python -m timeit -s "import numpy as np" -s "import itertools" -s "a = np.array([1,2,3,4,5,6,7,8,9])" -s "index=[2,3,6]" "a = np.array(list(itertools.compress(a, [i not in index for i in range(len(a))])))"
100000 loops, best of 3: 12.9 usec per loop

python -m timeit -s "import numpy as np" -s "a = np.array([1,2,3,4,5,6,7,8,9])" -s "index=[2,3,6]" "np.delete(a, index)"
10000 loops, best of 3: 108 usec per loop

To dość znacząca różnica (w przeciwnym kierunku, niż się spodziewałem), ktoś ma pojęcie, dlaczego tak się dzieje?

Co dziwniejsze, przekazywanie numpy.delete()listy działa gorzej niż zapętlanie listy i nadawanie jej pojedynczych wskaźników.

python -m timeit -s "import numpy as np" -s "a = np.array([1,2,3,4,5,6,7,8,9])" -s "index=[2,3,6]" "for i in index:" "    np.delete(a, i)"
10000 loops, best of 3: 33.8 usec per loop

Edycja: Wydaje się, że ma to związek z rozmiarem tablicy. Przy dużych tablicach numpy.delete()jest znacznie szybszy.

python -m timeit -s "import numpy as np" -s "import itertools" -s "a = np.array(list(range(10000)))" -s "index=[i for i in range(10000) if i % 2 == 0]" "a = np.array(list(itertools.compress(a, [i not in index for i in range(len(a))])))"
10 loops, best of 3: 200 msec per loop

python -m timeit -s "import numpy as np" -s "a = np.array(list(range(10000)))" -s "index=[i for i in range(10000) if i % 2 == 0]" "np.delete(a, index)"
1000 loops, best of 3: 1.68 msec per loop

Oczywiście to wszystko jest dość nieistotne, ponieważ zawsze powinieneś dążyć do jasności i unikać odkrywania koła na nowo, ale uważam to za trochę interesujące, więc pomyślałem, że zostawię to tutaj.


2
Uważaj na to, co faktycznie porównujesz! Masz a = delte_stuff(a)w swojej pierwszej iteracji, która azmniejsza się z każdą iteracją. Kiedy używasz funkcji wbudowanej, nie zapisujesz wartości z powrotem do a, która zachowuje oryginalny rozmiar! Poza tym możesz drastycznie przyspieszyć swoją funkcję, gdy utworzysz zestaw indexi sprawdź, czy chcesz usunąć element. Naprawiając obie rzeczy, dostaję za 10 000 pozycji: 6,22 ms na pętlę z twoją funkcją, 4,48 ms dla numpy.delete, co jest mniej więcej tym, czego możesz się spodziewać.
Michael,

2
Dwie dodatkowe wskazówki: Zamiast np.array(list(range(x)))używać np.arange(x)i do tworzenia indeksu możesz użyć np.s_[::2].
Michael,

1

Jeśli nie znasz indeksu, nie możesz go użyć logical_and

x = 10*np.random.randn(1,100)
low = 5
high = 27
x[0,np.logical_and(x[0,:]>low,x[0,:]<high)]

1

Używanie np.deletejest najszybszym sposobem na zrobienie tego, jeśli znamy wskaźniki elementów, które chcemy usunąć. Jednak dla kompletności dodam inny sposób „usuwania” elementów tablicy za pomocą maski logicznej utworzonej za pomocą np.isin. Ta metoda pozwala nam usunąć elementy, określając je bezpośrednio lub według ich indeksów:

import numpy as np
a = np.array([1, 2, 3, 4, 5, 6, 7, 8, 9])

Usuń według indeksów :

indices_to_remove = [2, 3, 6]
a = a[~np.isin(np.arange(a.size), indices_to_remove)]

Usuń według elementów (nie zapomnij odtworzyć oryginału, aponieważ został przepisany w poprzednim wierszu):

elements_to_remove = a[indices_to_remove]  # [3, 4, 7]
a = a[~np.isin(a, elements_to_remove)]

0

Usuń określony indeks (usunąłem 16 i 21 z matrycy)

import numpy as np
mat = np.arange(12,26)
a = [4,9]
del_map = np.delete(mat, a)
del_map.reshape(3,4)

Wynik:

array([[12, 13, 14, 15],
      [17, 18, 19, 20],
      [22, 23, 24, 25]])

0

Możesz także użyć zestawów:

a = numpy.array([10, 20, 30, 40, 50, 60, 70, 80, 90])
the_index_list = [2, 3, 6]

the_big_set = set(numpy.arange(len(a)))
the_small_set = set(the_index_list)
the_delta_row_list = list(the_big_set - the_small_set)

a = a[the_delta_row_list]
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.