2010-10-06 17 views
49

que tienen una matriz que podría tener este aspecto:filas eliminación en la matriz numpy

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

Tenga en cuenta que una de las filas tiene un valor cero al final. Quiero eliminar cualquier fila que contenga un cero, mientras mantengo cualquier fila que contenga valores distintos de cero en todas las celdas.

Pero la matriz tendrá diferentes números de filas cada vez que se llene, y los ceros se ubicarán en filas diferentes cada vez.

consigo el número de elementos no nulos de cada fila con la siguiente línea de código:

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

para la matriz anterior, NumNonzeroElementsInRows contiene: [5 4]

Los cinco indica que todos los valores posibles en la fila 0 son distintos de cero, mientras que los cuatro indican que uno de los valores posibles en la fila 1 es cero.

Por lo tanto, estoy tratando de utilizar las siguientes líneas de código para buscar y eliminar filas que contienen valores cero.

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

Pero por alguna razón, no parece este código para hacer nada, a pesar de hacer un montón de comandos de impresión indica que todas las variables parecen estar poblar correctamente que conduce hasta el código.

Debe haber alguna manera fácil de simplemente "eliminar cualquier fila que contenga un valor cero".

¿Alguien puede mostrarme qué código escribir para lograr esto?

Respuesta

4

Esto es similar a su enfoque original, y utilizará menos espacio que unutbu's answer, pero sospecho que será más 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]]) 

Por cierto, su línea p.delete() no funciona para mí - ndarray s no tienen un atributo .delete.

+8

un poco más simple: p [~ (p == 0) .any (1)] o más explícito para las filas: p [~ (p == 0) .any (1),:] – user333700

+0

@ user333700 - Esa debería ser una respuesta - ¡definitivamente obtendrías mi voto! 'any' es mucho más claro que' sum' en este uso. – mtrw

12

Aquí hay un chiste (sí, es similar a la de user333700, pero un poco más directa):

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

Por cierto, este método es mucho, mucho más rápido que el método gama de máscaras para grandes matrices . Para una matriz de 2048 x 5, este método es aproximadamente 1000 veces más rápido.

Por cierto, el método de user333700 (de su comentario) fue un poco más rápido en mis pruebas, aunque me sorprende por qué.

+3

"cualquiera" puede provocar un cortocircuito, tan pronto como se detecte el primer caso verdadero, puede detenerse, mientras que "todos" tiene que verificar todas las condiciones. Entonces, no ("~" en numpy) cualquiera, debería en general ser más rápido que todos. – user333700

+3

@ user333700, ambos pueden provocar un cortocircuito, solo para cosas diferentes. 'cualquier' cortocircuito a verdadero en el primer caso verdadero detectado; 'todos' cortocircuitos a falso en el primer caso falso detectado. En este caso, el cortocircuito debería ser un empate, pero hacer el extra no debería hacerlo más lento en mi opinión. –

2

numpy proporciona una función simple para hacer exactamente lo mismo: suponiendo que tiene una matriz 'a' enmascarada, llamando a numpy.ma.compress_rows (a) eliminará las filas que contienen un valor enmascarado. Supongo que esto es mucho más rápido de esta manera ...

96

La forma más sencilla de eliminar filas y columnas de las matrices es el método numpy.delete.

Supongamos que tengo la siguiente matriz x:

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

Para eliminar la primera fila, hacer esto:

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

Para eliminar la tercera columna, hacer esto:

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

Para que pueda encontrar los índices de las filas que tienen un 0 en ellos, póngalos en una lista o una tupla y pasa esto como el segundo argumento de la función.

+0

Gracias! Tuve el mismo problema, y ​​no pude entender por qué simplemente llamar a 'numpy.delete (x, index)' no funcionó. – Antimony

+3

tenga en cuenta que [numpy delete() docs] (https://docs.scipy.org/doc/numpy/reference/generated/numpy.delete.html) indica que "A menudo es preferible usar una máscara booleana" ya que se devuelve una nueva matriz; se proporciona un ejemplo debajo de ese enlace – arturomp

0

Podría ser demasiado tarde para responder a esta pregunta, pero quería compartir mi opinión para el beneficio de la comunidad. Para este ejemplo, permítame llamar a su matriz 'ANOVA', y supongo que está tratando de eliminar las filas de esta matriz con 0 solo en la quinta columna.

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]