tutoriales.com

Mascaras Booleanas y Filtrado Avanzado con Pandas y NumPy 🎭

Descubre el poder oculto de las operaciones vectorizadas y las mascaras booleanas en Pandas y NumPy. Este tutorial te ensenara tecnicas avanzadas para filtrar, seleccionar y manipular tus datos de manera eficiente y elegante.

Intermedio8 min de lectura6 views
Reportar error

Introduccion al Filtrado Booleano 🎭

El análisis de datos efectivo comienza con la capacidad de aislar la información relevante dentro de un mar de registros. ¿Te ha pasado que tienes un DataFrame masivo y necesitas encontrar exactamente aquellas filas que cumplen con condiciones complejas? Aquí es donde entran en juego las máscaras booleanas. Una máscara booleana es, en esencia, un arreglo de valores verdaderos (True) y falsos (False) que corresponden a la posición de los elementos en otra estructura de datos.

En el ecosistema de Python para ciencia de datos, NumPy y Pandas hacen que este proceso sea extremadamente rápido gracias a la vectorización. En lugar de usar bucles for tradicionales que evalúan fila por fila —un método lentísimo y poco práctico—, las operaciones booleanas se aplican a todo el conjunto de datos de golpe en lenguaje C optimizado.

💡 Consejo: Dominar el filtrado booleano reducirá drásticamente la cantidad de código que escribes y mejorará el rendimiento de tus scripts de análisis de datos.

Fundamentos de NumPy: Arreglos y Condiciones

Antes de saltar a Pandas, es vital entender cómo operan las condiciones lógicas a nivel de NumPy. Cuando aplicamos un operador de comparación a un arreglo de NumPy, este no devuelve un único True o False, sino un nuevo arreglo de la misma forma con resultados booleanos.

Operadores de Comparación y Lógicos

A diferencia de Python puro, donde usamos las palabras clave and, or y not, en NumPy y Pandas debemos utilizar operadores bit a bit debido a la precedencia de operadores:

  • & : Operador lógico AND (Y)
  • | : Operador lógico OR (O)
  • ~ : Operador lógico NOT (NO / Negación)

Veamos esto en un ejemplo de código:

import numpy as np

# Creamos un arreglo de calificaciones
calificaciones = np.array([85, 42, 90, 78, 60, 95, 33])

# Creamos una mascara para calificaciones aprobatorias (mayor o igual a 60)
mascara_aprobados = calificaciones >= 60
print("Mascara:", mascara_aprobados)

# Aplicamos la mascara para obtener solo los valores que cumplen la condicion
aprobados = calificaciones[mascara_aprobados]
print("Aprobados:", aprobados)
Arreglo de entrada 85 42 90 Condición: >= 60 Máscara Booleana True False True Resultado Filtrado 85 90 Solo los elementos que cumplen la condición (True) se mantienen

Filtrado Avanzado en Pandas con boolean indexing

Cuando pasamos a Pandas, el concepto de máscara booleana se traslada a las Series y los DataFrames. Podemos evaluar columnas enteras utilizando la notación de corchetes o el método .loc.

Condicion Simple en un DataFrame

Imaginemos que tenemos un dataset de empleados y queremos filtrar aquellos que pertenecen al departamento de "Ventas".

import pandas as pd

# Datos de prueba
data = {
    'Nombre': ['Ana', 'Carlos', 'Elena', 'David', 'Sofía'],
    'Departamento': ['Ventas', 'IT', 'Ventas', 'HR', 'IT'],
    'Salario': [45000, 72000, 48000, 39000, 80000],
    'Antiguedad': [3, 5, 2, 1, 7]
}

df = pd.DataFrame(data)

# Filtrar empleados de Ventas
ventas_df = df[df['Departamento'] == 'Ventas']
print(ventas_df)
📌 Nota: Siempre que combines múltiples condiciones en Pandas, cada condición individual debe estar envuelta entre paréntesis `()`. De lo contrario, Python arrojará un error de sintaxis debido a la precedencia de operadores.

Condiciones Múltiples

¿Qué pasa si queremos buscar empleados de "IT" que ganen más de 75,000? Combinamos las condiciones usando el operador &:

# IT con salario mayor a 75000
it_senior = df[(df['Departamento'] == 'IT') & (df['Salario'] > 75000)]
print(it_senior)

Métodos Avanzados de Filtrado

Además de los operadores tradicionales, Pandas ofrece métodos nativos muy potentes que hacen que el código sea mucho más legible cuando evaluamos conjuntos de valores o patrones.

El Método .isin()

En lugar de escribir múltiples condiciones con | (ej. (df['Depto'] == 'IT') | (df['Depto'] == 'Ventas')), podemos usar .isin():

# Filtrar multiples departamentos
deptos_objetivo = ['Ventas', 'HR']
filtrado_deptos = df[df['Departamento'].isin(deptos_objetivo)]
print(filtrado_deptos)

El Método .between()

Ideal para rangos numéricos o fechas:

# Salarios entre 40000 y 70000 (inclusive por defecto)
salarios_medios = df[df['Salario'].between(40000, 70000)]
print(salarios_medios)

Búsqueda de Texto con .str.contains()

Para filtrar datos de tipo texto basados en subcadenas:

# Nombres que contengan la letra 'a' (case insensitive opcional)
ombres_con_a = df[df['Nombre'].str.contains('a', case=False, na=False)]
print(ombres_con_a)

Consultas Expresivas con el Método .query()

Si buscas una sintaxis más limpia y parecida a SQL para filtrar tus DataFrames, el método .query() es tu mejor aliado. Te permite escribir las condiciones como una cadena de texto.

# Filtrar usando .query()
resultado_query = df.query("Departamento == 'IT' and Salario > 70000")
print(resultado_query)
⚠️ Advertencia: Aunque `.query()` es excelente para legibilidad, puede ser ligeramente más lento en datasets pequeños en comparación con el filtrado booleano tradicional debido al coste de evaluar expresiones en tiempo de ejecución.

Uso de Variables en .query()

Puedes hacer referencia a variables externas utilizando el símbolo @:

salario_minimo = 50000
filtrado_dinamico = df.query("Salario >= @salario_minimo")
print(filtrado_dinamico)

Optimización y Buenas Prácticas

Cuando trabajas con millones de filas, la forma en que filtras tus datos importa. Aquí tienes algunas recomendaciones clave:

Paso 1: Prefiere operaciones vectorizadas frente a bucles iterativos como iterrows().
Paso 2: Utiliza tipos de datos categóricos (astype('category')) para columnas con pocas opciones repetidas antes de filtrar.
Paso 3: Si vas a realizar múltiples consultas sobre el mismo subconjunto, considera almacenar el resultado en una nueva variable o usar índices.

Comparativa de Rendimiento

Método de FiltradoLegibilidadRendimiento en Dataset GrandeComplejidad de Sintaxis
Indexación Booleana ([])MediaAltoMedia
Método .loc[]AltaAltoMedia-Alta
Método .query()Muy AltaMedio-AltoBaja
Bucles (iterrows)BajaMuy BajoAlta

Preguntas Frecuentes (FAQ)

¿Por qué obtengo un error al usar 'and' en lugar de '&' en Pandas? Python evalúa el operador and a nivel de un objeto booleano completo, no elemento por elemento en un arreglo. Como una Serie de Pandas contiene múltiples valores, Python no sabe si evaluar todo el objeto como True o False, por lo que exige el operador bit a bit & que realiza la operación elemento a elemento.
¿Cómo puedo invertir una condición de filtrado? Puedes usar el operador de negación ~ al principio de tu máscara booleana. Por ejemplo: df[~(df['Departamento'] == 'IT')] te devolverá todo lo que no sea IT.

Conclusión

El filtrado avanzado mediante máscaras booleanas en Pandas y NumPy es una habilidad fundamental para cualquier científico de datos. Desde operaciones lógicas básicas hasta el uso de métodos sofisticados como .isin(), .between() y .query(), ahora cuentas con las herramientas necesarias para extraer exactamente la información que requieres de tus conjuntos de datos con máxima eficiencia y elegancia. ¡Es hora de aplicarlo en tus propios proyectos! Pro

Tutoriales relacionados

Comentarios (0)

Aún no hay comentarios. ¡Sé el primero!