So entfernen Sie bestimmte Elemente in einem Numpy-Array


212

Wie kann ich bestimmte Elemente aus einem Numpy-Array entfernen? Sag ich habe

import numpy as np

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

Ich möchte dann entfernen 3,4,7aus a. Ich weiß nur den Index der Werte ( index=[2,3,6]).

Antworten:


284

Use numpy.delete () - Gibt ein neues Array mit Unterarrays entlang einer gelöschten Achse zurück

numpy.delete(a, index)

Für Ihre spezielle Frage:

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

Beachten Sie, dass numpy.delete()ein neues Array zurückgegeben wird, da Array-Skalare ähnlich wie Zeichenfolgen in Python unveränderlich sind. Jedes Mal, wenn eine Änderung daran vorgenommen wird, wird ein neues Objekt erstellt. Dh um die delete() Dokumente zu zitieren :

"Eine Kopie von arr mit den durch obj angegebenen Elementen wurde entfernt. Beachten Sie, dass das Löschen nicht an Ort und Stelle erfolgt ..."

Wenn der von mir veröffentlichte Code ausgegeben wurde, ist dies das Ergebnis der Ausführung des Codes.


1
@IngviGautsson Als Sie Ihre Bearbeitung vorgenommen haben, haben Sie auch die korrekten Werte für die Elemente von 2, 3, 6 auf 3, 4, 7 geändert. Wenn Sie den Code jetzt ausführen, erhalten Sie nicht die richtige Ausgabe, wie dies ursprünglich der Fall war "
Levon

1
AttributeError: 'list' Objekt hat kein Attribut 'delete'
munmunbb

3
@IngviGautsson Nein, Ihr Kommentar ist irreführend. Dies funktioniert wie erwartet. In der Dokumentation von numpy.delete () wird jedoch darauf hingewiesen, dass "häufig die Verwendung einer booleschen Maske vorzuziehen ist"; Ein Beispiel dafür wird ebenfalls gegeben.
Biggsy

1
@Levon können Sie Beispiele für 2D hinzufügen?
MattS

7
@IngviGautsson Du liegst falsch. Zum Löschen sind die Indizes der Elemente erforderlich, nicht die Elemente selbst.
Le Frite

64

Es gibt eine eingebaute Numpy-Funktion, die dabei hilft.

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
Gut zu wissen. Ich dachte, dass np.delete langsamer sein würde, aber leider sagt timeit für 1000 ganze Zahlen, dass delete x2 schneller ist.
wbg

1
Dies ist großartig, da es mit den Werten des Arrays arbeitet , anstatt den Index / die Indizes angeben zu müssen, die Sie entfernen möchten. Zum Beispiel:np.setdiff1d(np.array(['one','two']),np.array(['two', 'three']))
MD004

Dies sortiert auch die Ausgabe, die möglicherweise nicht das ist, was gewünscht wird. Ansonsten sehr schön.
Rayzinnz

Die Frage lautet "Ich weiß nur den Index der Werte". Es geht also darum , Elemente anhand ihrer Indizes zu entfernen und nicht mit ihren Werten
Sherzod vor

35

Ein Numpy-Array ist unveränderlich , dh Sie können ein Element technisch nicht daraus löschen. Sie können jedoch ein neues Array ohne die nicht gewünschten Werte erstellen:

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

1
+1 für die Erwähnung von "unveränderlich". Es ist gut daran zu denken, dass numpy Arrays nicht gut für schnelle Größenänderungen (Anhängen / Löschen von Elementen) sind
eumiro

38
Technisch gesehen sind Numpy-Arrays veränderlich. Beispiel: a[0]=1Wird aan Ort und Stelle geändert . Die Größe kann jedoch nicht geändert werden.
Btel

3
Die Definition besagt, dass es unveränderlich ist, aber wenn Sie durch Zuweisen eines neuen Werts Änderungen vornehmen können, wie ist es dann unveränderlich?
JSR

16

So löschen Sie nach Wert:

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

Die Frage betrifft das Entfernen von Elementen nach Indizes und nicht das Entfernen von Elementen mit einem bestimmten Wert
Sherzod vor

5

Da ich keine numpy Person bin, habe ich eine Aufnahme gemacht mit:

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

Nach meinen Tests übertrifft dies numpy.delete(). Ich weiß nicht, warum das der Fall sein würde, vielleicht aufgrund der geringen Größe des ursprünglichen Arrays?

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

Das ist ein ziemlich bedeutender Unterschied (in die entgegengesetzte Richtung zu dem, was ich erwartet hatte). Hat jemand eine Idee, warum dies der Fall sein würde?

Noch seltsamer ist es, numpy.delete()eine Liste zu übergeben, die schlechter ist, als die Liste zu durchlaufen und ihr einzelne Indizes zu geben.

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

Bearbeiten: Es scheint mit der Größe des Arrays zu tun zu haben. Ist bei großen Arrays numpy.delete()deutlich schneller.

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

Natürlich ist das alles ziemlich irrelevant, da Sie immer auf Klarheit achten und vermeiden sollten, das Rad neu zu erfinden, aber ich fand es ein wenig interessant, also dachte ich, ich würde es hier lassen.


2
Sei vorsichtig mit dem, was du tatsächlich vergleichst! Sie haben a = delte_stuff(a)in Ihrer ersten Iteration, die amit jeder Iteration kleiner wird. Wenn Sie die Inbuild-Funktion verwenden, speichern Sie den Wert nicht zurück in a, wodurch a in der Originalgröße bleibt! Außerdem können Sie Ihre Funktion drastisch beschleunigen, wenn Sie einen Satz erstellen indexund prüfen, ob ein Element gelöscht werden soll oder nicht. Wenn ich beide Dinge behebe, bekomme ich für 10.000 Elemente: 6,22 ms pro Schleife mit Ihrer Funktion, 4,48 ms für numpy.delete, was ungefähr das ist, was Sie erwarten würden.
Michael

2
Zwei weitere Hinweise: Anstelle der np.array(list(range(x)))Verwendung np.arange(x)und zum Erstellen des Index können Sie auch verwenden np.s_[::2].
Michael

1

Wenn Sie den Index nicht kennen, können Sie ihn nicht verwenden 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

Die Verwendung np.deleteist der schnellste Weg, wenn wir die Indizes der Elemente kennen, die wir entfernen möchten. Der Vollständigkeit halber möchte ich jedoch eine andere Möglichkeit zum "Entfernen" von Array-Elementen mithilfe einer Booleschen Maske hinzufügen, die mit Hilfe von erstellt wurde np.isin. Mit dieser Methode können wir die Elemente entfernen, indem wir sie direkt oder anhand ihrer Indizes angeben:

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

Durch Indizes entfernen :

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

Nach Elementen entfernen (vergessen Sie nicht, das Original aneu zu erstellen, da es in der vorherigen Zeile neu geschrieben wurde):

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

0

Entfernen Sie einen bestimmten Index (ich habe 16 und 21 aus der Matrix entfernt)

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

Ausgabe:

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

0

Sie können auch Sets verwenden:

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]
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.