¿Cómo elimino las filas de una matriz numpy en función de varias condiciones?

Tengo un archivo con 4 columnas y miles de filas. Quiero eliminar las filas cuyos elementos en la primera columna están dentro de un cierto rango. Por ejemplo, si los datos en mi archivo son los siguientes:

18 6.215 0.025 19 6.203 0.025 20 6.200 0.025 21 6.205 0.025 22 6.201 0.026 23 6.197 0.026 24 6.188 0.024 25 6.187 0.023 26 6.189 0.021 27 6.188 0.020 28 6.192 0.019 29 6.185 0.020 30 6.189 0.019 31 6.191 0.018 32 6.188 0.019 33 6.187 0.019 34 6.194 0.021 35 6.192 0.024 36 6.193 0.024 37 6.187 0.026 38 6.184 0.026 39 6.183 0.027 40 6.189 0.027 

Quiero eliminar las filas cuyo primer elemento es entre 20 y 25 o entre 30 y 35. Eso significa que la salida que espero es:

 18 6.215 0.025 19 6.203 0.025 26 6.189 0.021 27 6.188 0.020 28 6.192 0.019 29 6.185 0.020 36 6.193 0.024 37 6.187 0.026 38 6.184 0.026 39 6.183 0.027 40 6.189 0.027 

¿Cómo podría hacer esto?

Si quieres seguir usando el numpy , la solución no es difícil.

 data = data[np.logical_not(np.logical_and(data[:,0] > 20, data[:,0] < 25))] data = data[np.logical_not(np.logical_and(data[:,0] > 30, data[:,0] < 35))] 

O si quieres combinarlo todo en una sola statement,

 data = data[ np.logical_not(np.logical_or( np.logical_and(data[:,0] > 20, data[:,0] < 25), np.logical_and(data[:,0] > 30, data[:,0] < 35) )) ] 

Para explicar, las sentencias condicionales como data[:,0] < 25 crean matrices booleanas que siguen, elemento por elemento, donde la condición en una matriz es verdadera o falsa. En este caso, le indica dónde está la primera columna de datos menos de 25.

También puede indexar matrices numpy con estas matrices booleanas. Una statement como data[data[:,0] > 30] extrae todas las filas donde data[:,0] > 30 es verdadera, o todas las filas donde el primer elemento es mayor que 30. Este tipo de indexación condicional es cómo extrae las filas (o columnas, o elementos) que quieras.

Finalmente, necesitamos herramientas lógicas para combinar matrices booleanas elemento por elemento. Las declaraciones regulares and , or , y not , no funcionan porque intentan combinar las matrices booleanas en conjunto. Afortunadamente, numpy proporciona un conjunto de estas herramientas para su uso en forma de np.logical_and , np.logical_or y np.logical_not . Con estos, podemos combinar nuestros arreglos booleanos de forma elemental para encontrar filas que satisfagan condiciones más complicadas.

En el caso especial pero frecuente de que el criterio de selección es si un valor alcanza un intervalo, uso el abs() de la diferencia a la mitad del intervalo, especialmente si midInterval tiene un significado físico:

 data = data[abs(data[:,0] - midInterval) < deviation] # '<' for keeping the interval 

Si el tipo de datos es entero y el valor medio no (como en la solicitud de Jun), podría duplicar los valores en lugar de la conversión a flotación (los errores de redondeo se convierten en> 1 para los enteros grandes):

 data = data[abs(2*data[:,0] - sumOfLimits) > deltaOfLimits] 

Repita para eliminar dos intervalos. Con los límites en la pregunta de Jun:

 data = data[abs(2*data[:,0] - 45) > 3] data = data[abs(2*data[:,0] - 65) > 3] 

Encuentre a continuación mi solución al problema de eliminar filas específicas de una matriz numpy. La solución se proporciona como una sola línea de la forma:

 # Remove the rows whose first item is between 20 and 25 A = np.delete(A, np.where( np.bitwise_and( (A[:,0]>=20), (A[:,0]<=25) ) )[0], 0) 

y se basa en funciones numpy puras (np.bitwise_and, np.where, np.delete).

 A = np.array( [ [ 18, 6.215, 0.025 ], [ 19, 6.203, 0.025 ], [ 20, 6.200, 0.025 ], [ 21, 6.205, 0.025 ], [ 22, 6.201, 0.026 ], [ 23, 6.197, 0.026 ], [ 24, 6.188, 0.024 ], [ 25, 6.187, 0.023 ], [ 26, 6.189, 0.021 ], [ 27, 6.188, 0.020 ], [ 28, 6.192, 0.019 ], [ 29, 6.185, 0.020 ], [ 30, 6.189, 0.019 ], [ 31, 6.191, 0.018 ], [ 32, 6.188, 0.019 ], [ 33, 6.187, 0.019 ], [ 34, 6.194, 0.021 ], [ 35, 6.192, 0.024 ], [ 36, 6.193, 0.024 ], [ 37, 6.187, 0.026 ], [ 38, 6.184, 0.026 ], [ 39, 6.183, 0.027 ], [ 40, 6.189, 0.027 ] ] ) # Remove the rows whose first item is between 20 and 25 A = np.delete(A, np.where( np.bitwise_and( (A[:,0]>=20), (A[:,0]<=25) ) )[0], 0) # Remove the rows whose first item is between 30 and 35 A = np.delete(A, np.where( np.bitwise_and( (A[:,0]>=30), (A[:,0]<=35) ) )[0], 0) >>> A array([[ 1.80000000e+01, 6.21500000e+00, 2.50000000e-02], [ 1.90000000e+01, 6.20300000e+00, 2.50000000e-02], [ 2.60000000e+01, 6.18900000e+00, 2.10000000e-02], [ 2.70000000e+01, 6.18800000e+00, 2.00000000e-02], [ 2.80000000e+01, 6.19200000e+00, 1.90000000e-02], [ 2.90000000e+01, 6.18500000e+00, 2.00000000e-02], [ 3.60000000e+01, 6.19300000e+00, 2.40000000e-02], [ 3.70000000e+01, 6.18700000e+00, 2.60000000e-02], [ 3.80000000e+01, 6.18400000e+00, 2.60000000e-02], [ 3.90000000e+01, 6.18300000e+00, 2.70000000e-02], [ 4.00000000e+01, 6.18900000e+00, 2.70000000e-02]]) 

No necesitas agregar complejidad con numpy para esto. Supongo que está leyendo su archivo en una lista de listas aquí (cada fila es una lista dentro de la lista general de datos como esta: ((18, 6.215, 0.025), (19, 6.203, 0.025),. ..)). En cuyo caso use la siguiente regla:

 for row in data: if((row[0] > 20 and row[0] < 25) or (row[0] > 30 and row[0] < 35)): data.remove(row)