Eliminar filas en NumPy de manera eficiente

Tengo una gran matriz numpy con muchos valores de identificación (llámelo X):

X:
id   rating
1    88
2    99
3    77
4    66
...

etc. También tengo otra matriz numerosa de "ID incorrectos", que significan filas que me gustaría eliminar de X.

B: [2, 3]

Entonces, cuando termine, me gustaría:

X:
id   rating
1    88
4    66

¿Cuál es la forma más limpia de hacer esto, sin iterar?

preguntado el 28 de agosto de 11 a las 03:08

Quizás relevante para sus intereses: stackoverflow.com/questions/1962980/… -

Específicamente la solución más votada. -

3 Respuestas

Esta es la forma más rápida que se me ocurrió:

import numpy

x = numpy.arange(1000000, dtype=numpy.int32).reshape((-1,2))
bad = numpy.arange(0, 1000000, 2000, dtype=numpy.int32)

print x.shape
print bad.shape

cleared = numpy.delete(x, numpy.where(numpy.in1d(x[:,0], bad)), 0)
print cleared.shape

Esto imprime:

(500000, 2)
(500,)
(499500, 2)

y corre mucho más rápido que un ufunc. Utilizará algo de memoria adicional, pero si eso está bien para usted depende de qué tan grande sea su matriz.

Explicación:

  • La numpy.in1d devuelve una matriz del mismo tamaño que x que contiene True si el elemento está en el bad matriz, y False de otra manera.
  • La numpy donde convierte eso True/False matriz en una matriz de enteros que contiene los valores de índice donde la matriz fue True.
  • Luego pasa las ubicaciones del índice a numpy.delete, diciéndole que elimine a lo largo del primer eje (0)

Respondido 28 ago 11, 20:08

+1, sospecho que esta es la mejor solución (evita un ufunc y es muy rápido en comparación con el mío). - doug

¡Gracias! Esto es mucho más rápido para mí que la solución a la que se hace referencia en los otros comentarios (stackoverflow.com/questions/1962980/…) - thegreatt

reproducir la especificación del problema de OP:

X = NP.array('1 88 2 99 3 77 4 66'.split(), dtype=int).reshape(4, 2)
bad_ids = [3,2]
bad_ideas = set(bad_ideas)    # see jterrance comment below this Answer

Vectorizar un bult-in de las pruebas de membresía de Python, es decir, X en Y sintaxis

@NP.vectorize
def filter_bad_ids(id) :
    return id not in bad_ids


>>> X_clean = X[filter_bad_ids(X[:,0])]
>>> X_clean                                # result
   array([[ 1, 88],
          [ 4, 66]])

Respondido 28 ago 11, 22:08

No in tomarse O (N) tiempo para una lista? Probablemente deberías hacer bad_ids = set([3,2]) - terraza

@ jterrance--gracias (edité mi respuesta de acuerdo con su comentario). - doug

Agradezco la ayuda, pero la otra solución funciona significativamente más rápido en mi conjunto de datos. - thegreatt

Si desea eliminar por completo la información de las identificaciones incorrectas, intente esto:

x = x[numpy.in1d(x[:,0], bad, invert=True)]

Esta solución utiliza bastante poca memoria y debería ser muy rápida. (bad se convierte en una matriz numpy, por lo que no debería ser un conjunto para que esto funcione, vea la nota en http://docs.scipy.org/doc/numpy/reference/generated/numpy.in1d.html)
Si lo malo es muy pequeño, podría ser un poco más rápido hacerlo en su lugar:

from functools import reduce
x = x[~reduce(numpy.logical_or, (x[:,0] == b for b in bad))]

Nota: La primera línea es necesaria solo en Python3.
Esto también usa poca memoria debido al uso de un generador.

Respondido 30 Oct 15, 03:10

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.