deletando linhas na matriz numpy


88

Eu tenho uma matriz que pode ser parecida com esta:

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

Observe que uma das linhas tem valor zero no final. Desejo excluir qualquer linha que contenha um zero, mantendo qualquer linha que contenha valores diferentes de zero em todas as células.

Mas a matriz terá diferentes números de linhas sempre que for preenchida e os zeros estarão localizados em diferentes linhas a cada vez.

Eu obtenho o número de elementos diferentes de zero em cada linha com a seguinte linha de código:

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

Para a matriz acima, NumNonzeroElementsInRowscontém: [5 4]

O cinco indica que todos os valores possíveis na linha 0 são diferentes de zero, enquanto o quatro indica que um dos valores possíveis na linha 1 é zero.

Portanto, estou tentando usar as seguintes linhas de código para localizar e excluir linhas que contêm valores zero.

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

Mas, por algum motivo, esse código não parece fazer nada, embora muitos comandos de impressão indiquem que todas as variáveis ​​parecem estar sendo preenchidas corretamente, levando ao código.

Deve haver uma maneira fácil de simplesmente "excluir qualquer linha que contenha um valor zero".

Alguém pode me mostrar qual código escrever para fazer isso?

Respostas:


163

A maneira mais simples de excluir linhas e colunas de arrays é o numpy.deletemétodo.

Suponha que eu tenha a seguinte matriz x:

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

Para excluir a primeira linha, faça o seguinte:

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

Para excluir a terceira coluna, faça o seguinte:

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

Assim, você pode encontrar os índices das linhas que têm um 0, colocá-los em uma lista ou tupla e passar isso como o segundo argumento da função.


Obrigado! Eu tive o mesmo problema e não conseguia descobrir por que simplesmente ligar numpy.delete(x, index)não funcionava.
Antimônio de

6
observe que os documentos numpy delete () indicam que "Freqüentemente, é preferível usar uma máscara booleana", pois uma nova matriz é retornada - um exemplo é fornecido nesse link
arturomp

1
@arturomp mas a máscara não é destrutiva. Uma chamada para delete () consome tempo / memória?
Nathan

13

Aqui está um liner (sim, é semelhante ao user333700, mas um pouco mais direto):

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

A propósito, este método é muito, muito mais rápido do que o método de matriz mascarada para grandes matrizes. Para uma matriz de 2048 x 5, esse método é cerca de 1000 vezes mais rápido.

A propósito, o método do user333700 (a partir de seu comentário) foi um pouco mais rápido em meus testes, embora me confunda o porquê.


3
"qualquer" pode entrar em curto-circuito, assim que o primeiro caso verdadeiro for detectado, ele pode parar, enquanto "todos" tem que verificar todas as condições. Portanto, não ("~" em numpy) nenhum, deve em geral ser mais rápido do que todos.
Josef

4
@ user333700, ambos podem entrar em curto-circuito, apenas para coisas diferentes. anycurto-circuitos para verdadeiro no primeiro caso verdadeiro detectado; allcurto-circuitos para falso no primeiro caso falso detectado. Nesse caso, o curto-circuito deve ser um empate, mas fazer o extra não deve torná-lo mais lento na minha opinião.
Justin Peel,

5

Isso é semelhante à sua abordagem original e usará menos espaço do que a resposta do unutbu , mas suspeito que será mais lento.

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

A propósito, sua linha p.delete()não funciona para mim - ndarraynão tem um .deleteatributo.


8
um pouco mais simples: p [~ (p == 0) .any (1)] ou mais explícito para linhas: p [~ (p == 0) .any (1),:]
Josef

2

numpy fornece uma função simples para fazer exatamente a mesma coisa: supondo que você tenha um array mascarado 'a', chamar numpy.ma.compress_rows (a) excluirá as linhas contendo um valor mascarado. Eu acho que é muito mais rápido assim ...


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

-1

Posso ser tarde demais para responder a essa pergunta, mas gostaria de compartilhar minha opinião para o benefício da comunidade. Para este exemplo, deixe-me chamar sua matriz de 'ANOVA', e estou assumindo que você está apenas tentando remover linhas dessa matriz com 0s apenas na 5ª coluna.

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