Comment supprimer des éléments spécifiques dans un tableau numpy

212

Comment puis-je supprimer certains éléments spécifiques d'un tableau numpy? Dis que j'ai

import numpy as np

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

Je veux ensuite retirer 3,4,7de a. Tout ce que je sais, c'est l'index des valeurs ( index=[2,3,6]).

Daniel Thaagaard Andreasen
la source

Réponses:

287

Utilisez numpy.delete () - retourne un nouveau tableau avec des sous-tableaux le long d'un axe supprimé

numpy.delete(a, index)

Pour votre question spécifique:

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

Notez que numpy.delete()retourne un nouveau tableau puisque les scalaires du tableau sont immuables, similaires aux chaînes en Python, donc chaque fois qu'un changement lui est apporté, un nouvel objet est créé. C'est-à-dire, pour citer les delete() documents :

"Une copie de arr avec les éléments spécifiés par obj supprimés. Notez que la suppression ne se produit pas sur place ..."

Si le code que je poste a une sortie, c'est le résultat de l'exécution du code.

Levon
la source
1
@IngviGautsson Lorsque vous avez effectué votre modification, vous avez également modifié les valeurs correctes des éléments de 2, 3, 6 à 3, 4, 7, si vous exécutez le code maintenant, vous n'obtenez pas la sortie correcte comme c'était le cas à l'origine. "
Levon
1
AttributeError: l'objet 'list' n'a pas d'attribut 'delete'
munmunbb
3
@IngviGautsson Non, votre commentaire est trompeur. Cela fonctionne comme prévu. Cependant, la documentation de numpy.delete () note que "souvent il est préférable d'utiliser un masque booléen"; un exemple en est également donné.
Biggsy
1
@Levon pouvez-vous ajouter des exemples pour la 2D?
MattS
7
@IngviGautsson Vous vous trompez. Cela prend les index des éléments à supprimer, pas les éléments eux-mêmes.
Le Frite
64

Il y a une fonction intégrée numpy pour vous aider.

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])
Zong
la source
7
Bon à savoir. Je pensais que np.delete serait plus lent mais hélas, timeit pour 1000 entiers dit que la suppression est x2 plus rapide.
wbg
1
C'est génial car il fonctionne sur les valeurs du tableau plutôt que d'avoir à fournir le ou les index que vous souhaitez supprimer. Par exemple:np.setdiff1d(np.array(['one','two']),np.array(['two', 'three']))
MD004
Cela trie également la sortie, qui peut ne pas être celle souhaitée. Sinon très sympa.
rayzinnz
La question dit "Tout ce que je sais, c'est l'index des valeurs". Il s'agit donc de supprimer des éléments par leurs index , pas de supprimer avec leurs valeurs
Sherzod
35

Un tableau Numpy est immuable , ce qui signifie que vous ne pouvez techniquement pas en supprimer un élément. Cependant, vous pouvez construire un nouveau tableau sans les valeurs que vous ne voulez pas, comme ceci:

b = np.delete(a, [2,3,6])
Digitalex
la source
1
+1 pour avoir mentionné «immuable». Il est bon de se rappeler que les tableaux numpy ne sont pas bons pour les changements rapides de taille (ajout / suppression d'éléments)
eumiro
38
techniquement, les tableaux numpy SONT mutables. Par exemple, ceci: a[0]=1modifie asur place. Mais ils ne peuvent pas être redimensionnés.
btel
3
La définition dit qu'elle est immuable, mais si en attribuant une nouvelle valeur elle vous laisse modifier, comment la rend-elle immuable?
JSR
16

Pour supprimer par valeur:

modified_array = np.delete(original_array, np.where(original_array == value_to_delete))
Prakhar Pandey
la source
La question porte sur la suppression d'éléments par index , et non sur la suppression d'éléments ayant une valeur spécifique
Sherzod
5

N'étant pas une personne engourdie, j'ai pris une photo avec:

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

Selon mes tests, cela surpasse numpy.delete(). Je ne sais pas pourquoi ce serait le cas, peut-être en raison de la petite taille du tableau initial?

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

C'est une différence assez importante (dans la direction opposée à ce que j'attendais), n'importe qui a une idée pourquoi ce serait le cas?

Encore plus étrange, passer numpy.delete()une liste est moins efficace que de parcourir la liste et de lui donner des indices uniques.

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

Edit: Cela semble être lié à la taille du tableau. Avec de grands tableaux, numpy.delete()est beaucoup plus rapide.

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

Évidemment, tout cela n'est pas pertinent, car vous devriez toujours aller pour plus de clarté et éviter de réinventer la roue, mais je l'ai trouvée un peu intéressante, alors j'ai pensé que je la laisserais ici.

Gareth Latty
la source
2
Soyez prudent avec ce que vous comparez réellement! Vous avez a = delte_stuff(a)dans votre première itération, ce qui adiminue à chaque itération. Lorsque vous utilisez la fonction inbuild, vous ne stockez pas la valeur dans un, qui conserve un dans la taille d'origine! En plus de cela, vous pouvez accélérer considérablement votre fonction lorsque vous créez un ensemble ouf de indexet vérifiez par rapport à cela, si vous souhaitez supprimer un élément. En corrigeant les deux choses, j'obtiens pour 10 000 éléments: 6,22 ms par boucle avec votre fonction, 4,48 ms pour numpy.delete, ce qui est à peu près ce à quoi vous vous attendez.
Michael
2
Deux autres conseils: au lieu d' np.array(list(range(x)))utiliser np.arange(x), et pour créer l'index, vous pouvez utiliser np.s_[::2].
Michael
1

Si vous ne connaissez pas l'index, vous ne pouvez pas utiliser logical_and

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

L'utilisation np.deleteest le moyen le plus rapide de le faire, si nous connaissons les indices des éléments que nous voulons supprimer. Cependant, pour être complet, permettez-moi d'ajouter une autre façon de "supprimer" les éléments du tableau à l'aide d'un masque booléen créé à l'aide de np.isin. Cette méthode nous permet de supprimer les éléments en les spécifiant directement ou par leurs indices:

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

Supprimer par indices :

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

Supprimer par éléments (n'oubliez pas de recréer l'original acar il a été réécrit sur la ligne précédente):

elements_to_remove = a[indices_to_remove]  # [3, 4, 7]
a = a[~np.isin(a, elements_to_remove)]
Andreas K.
la source
0

Supprimer un index spécifique (j'ai supprimé 16 et 21 de la matrice)

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

Production:

array([[12, 13, 14, 15],
      [17, 18, 19, 20],
      [22, 23, 24, 25]])
Raja Ahsan Zeb
la source
0

Vous pouvez également utiliser des ensembles:

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]
OlDor
la source