La indexación es una técnica usada en NumPy para acceder y manipular los valores de los arrays. A pesar de esto, cuando se trabaja con grandes volúmenes de datos la indexación básica puede no ser suficiente. En estos casos es cuando se puede recurrir a la indexación avanzada en NumPy. La indexación avanzada facilita la selección y manipulación de subarrays de una manera sencilla, flexible y eficiente, permitiendo el acceso a elementos o subconjuntos específicos de manera dinámica y sin la necesidad de bucles. En esta entrada, se explicarán algunos conceptos de indexación avanzada en NumPy, viendo su aplicación a algunos problemas habituales.
Ventajas de la indexación avanzada en NumPy
Cuando se necesita obtener algunos elementos específicos de un array en base a condiciones o posiciones de un gran conjunto de datos se puede usar la indexación. Pero, con la indexación básica, solo se pueden seleccionar elementos contiguos o rangos consecutivos. Algo que limita las posibilidades y puede requerir el uso de luces para realizar el proceso complejo. Por ejemplo, en una matriz, ¿cómo seleccionar elementos en [0,1], [1,2], y [2,0] de forma eficiente?
Solución: la indexación avanzada de NumPy
La indexación avanzada en Numpy permite seleccionar elementos específicos mediante técnicas como boolean masking (enmascaramiento booleano) o indexación por listas. Eliminando la necesidad de recurrir a bucles. Al mismo tiempo que mejora el redimieron y la legibilidad del código. Estas técnicas se explican a continuación:
- Indexación por listas: Permite realizar la selección de los elementos no contiguos de un array mediante una lista de índices en lugar de rangos. Facilitando la extracción de elementos en posiciones específicas. Ejemplo:
import numpy as np data = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]]) indices_filas = [0, 1, 2] indices_columnas = [1, 2, 0] seleccion = data[indices_filas, indices_columnas] print(seleccion)
[2 6 7]
Aquí, se han seleccionado los valores data[0,1]
, data[1,2]
y data[2,0]
de una forma eficiente y fácil de leer.
- Enmascaramiento booleano: Otra técnica avanzada es el enmascaramiento booleano, con la que se pueden seleccionar elementos en base a condiciones lógicas. Siendo algo especialmente útil para filtrar valores según criterios específicos, como números mayores que un umbral o valores específicos. Ejemplo:
mascara = data > 5 seleccion = data[mascara] print(seleccion)
[6 7 8 9]
En este caso, el array mascara
crea un filtro para los valores mayores a 5, extrayendo esos elementos sin bucles.
- Indexación combinada: Numpy permite combinar boolean masking con indexación por listas para realizar selecciones aún más complejas. Por ejemplo, se puede usar boolean masking para una dimensión y una lista de índices para otra, permitiendo de esta manera operaciones más avanzadas. Ejemplo:
data = np.array([[10, 20, 30], [40, 50, 60], [70, 80, 90]]) # Solo filas con valores en la segunda columna mayores a 20 filas_condicion = data[:, 1] > 20 # Seleccionamos solo la primera y tercera columna columnas_especificas = [0, 2] seleccion = data[filas_condicion][:, columnas_especificas] print(seleccion)
Aquí, se filtran las filas donde la segunda columna tiene valores mayores a 20 y se seleccionan solo las columnas 0 y 2.
Ejemplos prácticos
A continuación se muestran tres ejemplos prácticos en los que estas técnicas pueden ser de utilidad.
Extracción de elementos dispersos
En una matriz, se puede recurrir a la indexación por listas para obtener la diagonal principal de esta. Tal como se muestra en el siguiente ejemplo donde se seleccionan los elementos en la diagonal de una matriz de 4×4.
data = np.arange(16).reshape(4, 4) indices = [0, 1, 2, 3] seleccion = data[indices, indices] print(seleccion)
[ 0 5 10 15]
Seleccionar elementos con múltiples condiciones
Boolean masking se puede utilizar para filtrar datos en base a más de una condición. Por ejemplo, los valores en un array se puede buscar los valores que se encuentran en un rango, por encima de un valor y por debajo de otro. Esto es lo que se muestra en el siguiente código donde se seleccionan los elementos que cumplen con dos condiciones: valores entre 30 y 70.
data = np.random.randint(0, 100, (5, 5)) seleccion = data[(data > 30) & (data < 70)] print(seleccion)
[54 40 67 57 53 31 67 58 33 35 41]
Aplicación en Data Analysis: Filtrado de datos específicos
También se puede usar los valores de un array para filtrar el otro, permitiendo seleccionar los valores en base a un valor asociado. Por ejemplo, se puede tener en un array las temperaturas y en otro los días de la semana, pudiendo seleccionar los días en los que se supera una temperatura dada. Esto es lo que se muestra a continuación donde se seleccionan los días de la semana donde la temperatura máxima es mayor de 21.
temperaturas = np.array([21, 23, 21, 22, 20, 21, 19]) dias = np.array(['lunes', 'martes', 'miércoles', 'jueves', 'viernes', 'sábado', 'domingo']) seleccion = dias[temperaturas > 21] print(seleccion)
['martes' 'jueves']
Conclusiones
La indexación avanzada en Numpy ofrece la posibilidad de trabajar con arrays complejos sin necesidad de bucles. Con boolean masking, indexación por listas o la combinaciones de ambos, es posible realizar operaciones complejas de selección de datos de forma eficiente. Estos métodos no solo mejoran la velocidad del código, sino que también hacen que el proceso de manipulación de datos sea más intuitivo y fácil de leer.