Filtrar, ordenar y agrupar datos con pandas significa seleccionar filas según condiciones, reordenarlas por valores y calcular resúmenes por categorías, todo sin salir de Python.
Filtrado con condiciones booleanas
Un filtro booleano evalúa cada fila y devuelve True o False. Pandas conserva solo las filas donde el resultado es True.
La sintaxis base es:
df[df["columna"] condicion valor]
Por ejemplo, tienes un DataFrame de nómina de una empresa proveedora de FEMSA. Quieres ver solo a los empleados que ganan más de $15,000:
import pandas as pd
nomina = pd.DataFrame({
"nombre": ["Ana", "Luis", "Karla", "Jorge", "Sofía"],
"departamento": ["Ventas", "Logística", "Ventas", "RRHH", "Logística"],
"salario": [18500, 12000, 22000, 15000, 9800]
})
altos = nomina[nomina["salario"] > 15000]
print(altos)
Salida:
nombre departamento salario
0 Ana Ventas 18500
2 Karla Ventas 22000
Nota que el índice conserva los números originales (0 y 2). Esto es normal en pandas.
Filtros con múltiples condiciones
Puedes combinar condiciones con & (AND) y | (OR). Siempre encierra cada condición entre paréntesis. Si no lo haces, Python lanzará un error de precedencia.
# Empleados de Ventas con salario mayor a $16,000
resultado = nomina[(nomina["departamento"] == "Ventas") & (nomina["salario"] > 16000)]
print(resultado)
Salida:
nombre departamento salario
0 Ana Ventas 18500
2 Karla Ventas 22000
Otro caso práctico: un inventario de Liverpool donde quieres artículos agotados o con precio menor a $200:
inventario = pd.DataFrame({
"producto": ["Camisa", "Pantalón", "Tenis", "Cinturón", "Bolsa"],
"precio": [350, 180, 950, 150, 1200],
"stock": [40, 0, 15, 0, 8]
})
alerta = inventario[(inventario["stock"] == 0) | (inventario["precio"] < 200)]
print(alerta)
Salida:
producto precio stock
1 Pantalón 180 0
3 Cinturón 150 0
Filtrar con .isin()
Cuando necesitas comparar contra una lista de valores, usa .isin(). Es más limpio que encadenar varios |.
deptos_clave = ["Ventas", "Logística"]
filtrado = nomina[nomina["departamento"].isin(deptos_clave)]
print(filtrado)
Salida:
nombre departamento salario
0 Ana Ventas 18500
1 Luis Logística 12000
2 Karla Ventas 22000
4 Sofía Logística 9800
Ordenar datos con .sort_values()
.sort_values() reordena el DataFrame por una o varias columnas. El parámetro ascending controla si el orden es de menor a mayor (True) o de mayor a menor (False).
Sintaxis:
df.sort_values(by="columna", ascending=True)
Ejemplo: ordenar la nómina de mayor a menor salario:
ordenado = nomina.sort_values(by="salario", ascending=False)
print(ordenado)
Salida:
nombre departamento salario
2 Karla Ventas 22000
0 Ana Ventas 18500
3 Jorge RRHH 15000
1 Luis Logística 12000
4 Sofía Logística 9800
Puedes ordenar por dos columnas. Primero por departamento (A–Z) y luego por salario (mayor a menor):
ordenado2 = nomina.sort_values(
by=["departamento", "salario"],
ascending=[True, False]
)
print(ordenado2)
Esto es útil cuando presentas reportes a RRHH: ven cada área ordenada internamente por sueldo.
Agrupar datos con .groupby()
.groupby() divide el DataFrame por categorías y aplica una función de resumen a cada grupo. Es el equivalente de una tabla dinámica en Excel.
Sintaxis base:
df.groupby("columna_grupo")["columna_valor"].funcion()
Ejemplo: calcular el salario promedio por departamento en la nómina:
promedio = nomina.groupby("departamento")["salario"].mean()
print(promedio)
Salida:
departamento
Logística 10900.0
RRHH 15000.0
Ventas 20250.0
Name: salario, dtype: float64
El resultado es una Serie con el departamento como índice. Si necesitas un DataFrame, agrega .reset_index():
promedio_df = nomina.groupby("departamento")["salario"].mean().reset_index()
print(promedio_df)
Salida:
departamento salario
0 Logística 10900.0
1 RRHH 15000.0
2 Ventas 20250.0
Agrupar con varias métricas usando .agg()
Cuando necesitas más de una métrica al mismo tiempo, usa .agg(). Puedes calcular suma, promedio, mínimo y máximo en una sola instrucción.
resumen = nomina.groupby("departamento")["salario"].agg(
total="sum",
promedio="mean",
maximo="max",
minimo="min"
).reset_index()
print(resumen)
Salida:
departamento total promedio maximo minimo
0 Logística 21800 10900.0 12000 9800
1 RRHH 15000 15000.0 15000 15000
2 Ventas 40500 20250.0 22000 18500
Este tipo de resumen es exactamente lo que un gerente de Bimbo o Mercado Libre esperaría en un reporte ejecutivo.
Combinar filtro, orden y agrupación
En la práctica, combinas las tres operaciones. Imagina que solo quieres el resumen salarial de los departamentos con salario promedio mayor a $12,000:
resumen_filtrado = resumen[resumen["promedio"] > 12000].sort_values(
by="promedio", ascending=False
)
print(resumen_filtrado)
Salida:
departamento total promedio maximo minimo
2 Ventas 40500 20250.0 22000 18500
1 RRHH 15000 15000.0 15000 15000
Primero filtras, luego ordenas. El orden de las operaciones importa.
Errores comunes
Error 1: olvidar los paréntesis en condiciones múltiples.
Escribir df[df["a"] > 5 & df["b"] == 1] lanza un error. La forma correcta es df[(df["a"] > 5) & (df["b"] == 1)].
Error 2: usar = en lugar de == dentro del filtro.
df[df["departamento"] = "Ventas"] es un error de sintaxis. Para comparar siempre usas ==.
Error 3: no reasignar el resultado de .sort_values().
Como la lección anterior de limpieza enseñó, pandas no modifica el original. Siempre escribe df = df.sort_values(...) o guarda el resultado en una nueva variable.
Error 4: interpretar el índice de .groupby() como una columna.
Después de un groupby, el campo agrupado se convierte en índice, no en columna. Agrega .reset_index() para recuperarlo como columna normal y evitar confusiones al exportar a Excel.
Tabla de referencia rápida
| Operación | Método | Ejemplo corto |
|---|---|---|
| Filtrar una condición | df[df["col"] > valor] |
df[df["salario"] > 15000] |
| Filtrar varias condiciones | df[(cond1) & (cond2)] |
df[(df["depto"] == "Ventas") & (df["salario"] > 16000)] |
| Filtrar por lista | .isin([val1, val2]) |
df[df["depto"].isin(["Ventas", "RRHH"])] |
| Ordenar ascendente | .sort_values(by="col") |
df.sort_values(by="salario") |
| Ordenar descendente | .sort_values(by="col", ascending=False) |
df.sort_values(by="salario", ascending=False) |
| Agrupar y sumar | .groupby("col")["val"].sum() |
nomina.groupby("departamento")["salario"].sum() |
| Agrupar varias métricas | .groupby().agg(...) |
.agg(total="sum", promedio="mean") |