Como remover elementos específicos em uma matriz numpy


212

Como posso remover alguns elementos específicos de uma matriz numpy? Diga que eu tenho

import numpy as np

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

Eu quero remover 3,4,7de a. Tudo o que sei é o índice dos valores ( index=[2,3,6]).

Respostas:


284

Use numpy.delete () - retorna uma nova matriz com sub-matrizes ao longo de um eixo excluído

numpy.delete(a, index)

Para sua pergunta específica:

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

Observe que numpy.delete()retorna uma nova matriz, pois os escalares da matriz são imutáveis, semelhantes às seqüências de caracteres no Python, portanto, toda vez que uma alteração é feita, um novo objeto é criado. Ou seja, para citar os delete() documentos :

"Uma cópia de arr com os elementos especificados por obj removidos. Observe que a exclusão não ocorre no local ..."

Se o código que eu postar tiver saída, é o resultado da execução do código.


1
@IngviGautsson Ao fazer sua edição, você também alterou os valores corretos para os elementos de 2, 3, 6 para 3, 4, 7, se você executar o código agora, não obterá a saída correta, como era originalmente o caso. "estou revertendo a edição
— Levon

1
AttributeError: o objeto 'list' não tem atributo 'delete' #
— munmunbb 6/0617

3
@IngviGautsson Não, seu comentário é enganador. Isso funciona conforme o esperado. No entanto, a documentação de numpy.delete () observa que "geralmente é preferível usar uma máscara booleana"; um exemplo disso também é dado.
— Biggsy 19/10/19

1
@Levon você pode adicionar exemplos para 2D?
— 28519 MattS

7
@IngviGautsson Você está errado. São necessários os índices dos itens para excluir, não os próprios itens.
— Le Frite

64

Há uma função embutida numpy para ajudar nisso.

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
Bom saber. Eu estava pensando que o np.delete seria mais lento, mas, infelizmente, o timeit para 1000 números inteiros diz que a exclusão é x2 mais rápida.
— Wbg

1
Isso é ótimo porque opera com os valores da matriz em vez de precisar fornecer o índice / índices que você deseja remover. Por exemplo:np.setdiff1d(np.array(['one','two']),np.array(['two', 'three']))
— MD004

Isso também classifica a saída, que pode não ser o que se deseja. Caso contrário, muito bom.
— rayzinnz 25/03

A pergunta diz "Tudo o que sei é o índice dos valores". Então, trata-se de remover itens por seus índices , não remover com seus valores
— Sherzod

35

Uma matriz Numpy é imutável , o que significa que você tecnicamente não pode excluir um item dela. No entanto, você pode construir uma nova matriz sem os valores que não deseja, assim:

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

1
+1 por mencionar 'imutável'. É bom lembrar, que os arrays numpy não são bons para mudanças rápidas de tamanho (anexando / excluir elementos)
— eumiro

38
tecnicamente, matrizes numpy SÃO mutáveis. Por exemplo, isto: a[0]=1modifica ano local. Mas eles não podem ser redimensionados.
— btel

3
A definição diz que é imutável, mas se, ao atribuir um novo valor, você modificar, então o torna imutável?
— JSR

16

Para excluir por valor:

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

A questão é remover itens por índices , não remover itens com valor específico
— Sherzod

5

Não sendo uma pessoa entorpecida, tirei uma foto com:

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

De acordo com meus testes, isso supera numpy.delete(). Não sei por que esse seria o caso, talvez devido ao pequeno tamanho da matriz inicial?

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

Essa é uma diferença bastante significativa (na direção oposta ao que eu estava esperando), alguém tem alguma idéia de por que esse seria o caso?

Ainda mais estranhamente, passar numpy.delete()uma lista tem um desempenho pior do que percorrer a lista e fornecer índices únicos.

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

Editar: Parece ter a ver com o tamanho da matriz. Com matrizes grandes, numpy.delete()é significativamente mais rápido.

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

Obviamente, tudo isso é irrelevante, pois você sempre deve ter clareza e evitar reinventar a roda, mas achei um pouco interessante, então pensei em deixá-la aqui.


2
Cuidado com o que você realmente compara! Você tem a = delte_stuff(a)em sua primeira iteração, que adiminui a cada iteração. Quando você usa a função inbuild, não armazena o valor novamente em a, o que mantém a no tamanho original! Além disso, você pode acelerar drasticamente sua função, ao criar um conjunto de indexe de verificar se é para excluir ou não um item. Corrigindo as duas coisas, recebo 10k itens: 6,22 ms por loop com sua função, 4,48 ms por numpy.delete, o que é aproximadamente o que você esperaria.
— Michael

2
Mais duas dicas: em vez de np.array(list(range(x)))usar np.arange(x)e para criar o índice, você pode usar np.s_[::2].
— Michael Michael

1

Se você não conhece o índice, não pode usar 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

Usar np.deleteé a maneira mais rápida de fazer isso, se soubermos os índices dos elementos que queremos remover. No entanto, para completar, deixe-me adicionar outra maneira de "remover" os elementos da matriz usando uma máscara booleana criada com a ajuda de np.isin. Este método permite remover os elementos, especificando-os diretamente ou por seus índices:

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

Remover por índices :

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

Remova por elementos (não se esqueça de recriar o original, apois ele foi reescrito na linha anterior):

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

0

Remover índice específico (eu removi 16 e 21 da matriz)

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

Resultado:

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

0

Você também pode usar conjuntos:

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]
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.