Operaciones de agrupación en Pandas (groupby)
groupbyEs una de las funciones más potentes de Pandas. Permite agrupar los datos según una o más columnas y luego realizar operaciones de agregación, transformación o filtrado en cada grupo.
Uso básico de groupby
Agrupación por una sola columna
Ejemplo
import pandas as pd
# Crear datos de ejemplo
df = pd.DataFrame({
"Departamento": [Tecnología, "Ventas", Tecnología, Operaciones, "Ventas", Tecnología],
"Nombre": ["Zhang San", "Li Si", Wang Wu, "Zhao Liu", "Qian Qi", "Sun Ba"],
"Salario": [12000, 15000, 11000, 18000, 14000, 13000]
})
print(Datos originales:)
print(df)
print()
# Agrupar por departamento
grouped = df.groupby("Departamento")
print(fObjeto agrupado: {type(grouped)})
print(f"Número de grupos: {len(grouped)}")
print()
# Ver grupos
print(Datos de cada grupo:)
for name, group in grouped:
print(f"\n"Departamento: {name}")
print(group)
# Crear datos de ejemplo
df = pd.DataFrame({
"Departamento": [Tecnología, "Ventas", Tecnología, Operaciones, "Ventas", Tecnología],
"Nombre": ["Zhang San", "Li Si", Wang Wu, "Zhao Liu", "Qian Qi", "Sun Ba"],
"Salario": [12000, 15000, 11000, 18000, 14000, 13000]
})
print(Datos originales:)
print(df)
print()
# Agrupar por departamento
grouped = df.groupby("Departamento")
print(fObjeto agrupado: {type(grouped)})
print(f"Número de grupos: {len(grouped)}")
print()
# Ver grupos
print(Datos de cada grupo:)
for name, group in grouped:
print(f"\n"Departamento: {name}")
print(group)
Agrupar y agregar
Ejemplo
import pandas as pd
df = pd.DataFrame({
"Departamento": [Tecnología, "Ventas", Tecnología, Operaciones, "Ventas"],
"Salario": [12000, 15000, 11000, 18000, 14000]
})
print("Salario promedio por departamento:")
print(df.groupby("Departamento")["Salario"].mean())
print()
print("Suma agrupada por departamento:")
print(df.groupby("Departamento")["Salario"].sum())
print()
print("Conteo agrupado por departamento:")
print(df.groupby("Departamento").size())
df = pd.DataFrame({
"Departamento": [Tecnología, "Ventas", Tecnología, Operaciones, "Ventas"],
"Salario": [12000, 15000, 11000, 18000, 14000]
})
print("Salario promedio por departamento:")
print(df.groupby("Departamento")["Salario"].mean())
print()
print("Suma agrupada por departamento:")
print(df.groupby("Departamento")["Salario"].sum())
print()
print("Conteo agrupado por departamento:")
print(df.groupby("Departamento").size())
Agrupación por múltiples columnas
Ejemplo
import pandas as pd
df = pd.DataFrame({
"Año": ["2023", "2023", "2024", "2024"],
"Departamento": [Tecnología, "Ventas", Tecnología, "Ventas"],
"Salario": [12000, 15000, 13000, 16000]
})
print("Agrupar por año y departamento:")
print(df.groupby(["Año", "Departamento"])["Salario"].sum())
print()
# Salida como DataFrame
result = df.groupby(["Año", "Departamento"]).agg({
"Salario": "sum"
}).reset_index()
print(DataFrame resultante:)
print(result)
df = pd.DataFrame({
"Año": ["2023", "2023", "2024", "2024"],
"Departamento": [Tecnología, "Ventas", Tecnología, "Ventas"],
"Salario": [12000, 15000, 13000, 16000]
})
print("Agrupar por año y departamento:")
print(df.groupby(["Año", "Departamento"])["Salario"].sum())
print()
# Salida como DataFrame
result = df.groupby(["Año", "Departamento"]).agg({
"Salario": "sum"
}).reset_index()
print(DataFrame resultante:)
print(result)
Funciones de agregación comunes
Agregación única
| Función | Descripción |
|---|---|
sum() |
Suma |
mean() |
Media |
median() |
Mediana |
std() |
Desviación estándar |
min() / max() |
Mínimo/Máximo |
count() |
Conteo |
first() / last() |
Primer/último valor |
Ejemplo
import pandas as pd
df = pd.DataFrame({
"Departamento": [Tecnología, "Ventas", Tecnología, Operaciones],
"Salario": [12000, 15000, 11000, 18000]
})
# Llamada encadenada a múltiples agregaciones
print(Agregación en cadena:)
print(df.groupby("Departamento")["Salario"].agg(["sum", "mean", "max", "min"]))
df = pd.DataFrame({
"Departamento": [Tecnología, "Ventas", Tecnología, Operaciones],
"Salario": [12000, 15000, 11000, 18000]
})
# Llamada encadenada a múltiples agregaciones
print(Agregación en cadena:)
print(df.groupby("Departamento")["Salario"].agg(["sum", "mean", "max", "min"]))
Agregación personalizada
Ejemplo
import pandas as pd
import numpy as np
df = pd.DataFrame({
"Departamento": [Tecnología, "Ventas", Tecnología, Operaciones],
"Salario": [12000, 15000, 11000, 18000]
})
# Función de agregación personalizada
def range_func(x):
return x.max() - x.min()
print("Usando funciones personalizadas:")
print(df.groupby("Departamento")["Salario"].agg(range_func))
print()
# Agregación nombrada (recomendado)
print(Agregación con nombre:)
print(df.groupby("Departamento").agg(
Salario mínimo=("Salario", "min"),
Salario máximo=("Salario", "max"),
Salario promedio=("Salario", "mean")
))
import numpy as np
df = pd.DataFrame({
"Departamento": [Tecnología, "Ventas", Tecnología, Operaciones],
"Salario": [12000, 15000, 11000, 18000]
})
# Función de agregación personalizada
def range_func(x):
return x.max() - x.min()
print("Usando funciones personalizadas:")
print(df.groupby("Departamento")["Salario"].agg(range_func))
print()
# Agregación nombrada (recomendado)
print(Agregación con nombre:)
print(df.groupby("Departamento").agg(
Salario mínimo=("Salario", "min"),
Salario máximo=("Salario", "max"),
Salario promedio=("Salario", "mean")
))
transform
transform permite calcular sobre cada grupo manteniendo la forma original de los datos, devolviendo un resultado con la misma forma que los datos originales.
Ejemplo
import pandas as pd
df = pd.DataFrame({
"Departamento": [Tecnología, "Ventas", Tecnología, Operaciones, "Ventas"],
"Salario": [12000, 15000, 11000, 18000, 14000]
})
print("datos originales:")
print(df)
print()
# Calcular el salario promedio de cada departamento y transmitirlo a cada fila
df[Salario promedio por departamento] = df.groupby("Departamento")["Salario"].transform("mean")
print("Añadir el salario promedio del departamento:")
print(df)
print()
# Calcular la proporción del salario de cada persona en el departamento
df["Proporción de salario"] = df["Salario"] / df[Salario promedio por departamento]
print(Proporción salarial:)
print(df)
df = pd.DataFrame({
"Departamento": [Tecnología, "Ventas", Tecnología, Operaciones, "Ventas"],
"Salario": [12000, 15000, 11000, 18000, 14000]
})
print("datos originales:")
print(df)
print()
# Calcular el salario promedio de cada departamento y transmitirlo a cada fila
df[Salario promedio por departamento] = df.groupby("Departamento")["Salario"].transform("mean")
print("Añadir el salario promedio del departamento:")
print(df)
print()
# Calcular la proporción del salario de cada persona en el departamento
df["Proporción de salario"] = df["Salario"] / df[Salario promedio por departamento]
print(Proporción salarial:)
print(df)
Filtrado con filter
filter puede filtrar los datos según las condiciones de los grupos.
Ejemplo
import pandas as pd
df = pd.DataFrame({
"Departamento": [Tecnología, "Ventas", Tecnología, Operaciones, "Ventas", Tecnología],
"Salario": [12000, 15000, 11000, 18000, 14000, 13000]
})
print("datos originales:")
print(df)
print()
# Filtrar departamentos cuyo salario promedio sea mayor que 13000
print(Salario promedio por departamento > 13000:)
filtered = df.groupby("Departamento").filter(lambda x: x["Salario"].mean() > 13000)
print(filtered)
print()
# Filtrar grupos con cantidad mayor que 2
print("Número de miembros > 2:")
filtered2 = df.groupby("Departamento").filter(lambda x: len(x) > 2)
print(filtered2)
df = pd.DataFrame({
"Departamento": [Tecnología, "Ventas", Tecnología, Operaciones, "Ventas", Tecnología],
"Salario": [12000, 15000, 11000, 18000, 14000, 13000]
})
print("datos originales:")
print(df)
print()
# Filtrar departamentos cuyo salario promedio sea mayor que 13000
print(Salario promedio por departamento > 13000:)
filtered = df.groupby("Departamento").filter(lambda x: x["Salario"].mean() > 13000)
print(filtered)
print()
# Filtrar grupos con cantidad mayor que 2
print("Número de miembros > 2:")
filtered2 = df.groupby("Departamento").filter(lambda x: len(x) > 2)
print(filtered2)
apply: funciones personalizadas
apply permite aplicar una función personalizada a cada grupo.
Ejemplo
import pandas as pd
import numpy as np
df = pd.DataFrame({
"Departamento": [Tecnología, "Ventas", Tecnología, Operaciones],
"Salario": [12000, 15000, 11000, 18000]
})
# Aplicar una función personalizada a cada grupo
result = df.groupby("Departamento").apply(
lambda x: pd.Series({
"Total": x["Salario"].sum(),
"Media": x["Salario"].mean()
})
)
print(Resultado de agregación personalizada:)
print(result)
import numpy as np
df = pd.DataFrame({
"Departamento": [Tecnología, "Ventas", Tecnología, Operaciones],
"Salario": [12000, 15000, 11000, 18000]
})
# Aplicar una función personalizada a cada grupo
result = df.groupby("Departamento").apply(
lambda x: pd.Series({
"Total": x["Salario"].sum(),
"Media": x["Salario"].mean()
})
)
print(Resultado de agregación personalizada:)
print(result)
Práctica: análisis de datos de ventas
Ejemplo
import pandas as pd
# Simular datos de ventas
sales = pd.DataFrame({
"Fecha": pd.date_range("2024-01-01", periods=30, freq="D"),
"Producto": ["Teléfono móvil", "Computadora", "Tableta"] * 10,
"Canal": ["En línea"] * 15 + ["Fuera de línea"] * 15,
"Ventas": [1000, 2000, 1500] * 10
})
print(=== Análisis de datos de ventas ===\n")
# 1. Estadísticas por producto
print("1. Estadísticas por producto:")
product_summary = sales.groupby("Producto")["Ventas"].agg(["sum", "mean", "count"])
print(product_summary)
print()
# 2. Estadísticas por canal
print("2. Estadísticas por canal:")
channel_summary = sales.groupby("Canal")["Ventas"].sum()
print(channel_summary)
print()
# 3. Estadística cruzada por producto y canal
print(3. Estadística cruzada producto × canal:)
cross_summary = sales.groupby(["Producto", "Canal"])["Ventas"].sum().unstack()
print(cross_summary)
print()
# 4. Calcular la proporción de ventas de cada producto
print("4. Proporción de ventas:")
total = sales["Ventas"].sum()
product_pct = sales.groupby("Producto")["Ventas"].sum() / total * 100
print(product_pct.round(2))
# Simular datos de ventas
sales = pd.DataFrame({
"Fecha": pd.date_range("2024-01-01", periods=30, freq="D"),
"Producto": ["Teléfono móvil", "Computadora", "Tableta"] * 10,
"Canal": ["En línea"] * 15 + ["Fuera de línea"] * 15,
"Ventas": [1000, 2000, 1500] * 10
})
print(=== Análisis de datos de ventas ===\n")
# 1. Estadísticas por producto
print("1. Estadísticas por producto:")
product_summary = sales.groupby("Producto")["Ventas"].agg(["sum", "mean", "count"])
print(product_summary)
print()
# 2. Estadísticas por canal
print("2. Estadísticas por canal:")
channel_summary = sales.groupby("Canal")["Ventas"].sum()
print(channel_summary)
print()
# 3. Estadística cruzada por producto y canal
print(3. Estadística cruzada producto × canal:)
cross_summary = sales.groupby(["Producto", "Canal"])["Ventas"].sum().unstack()
print(cross_summary)
print()
# 4. Calcular la proporción de ventas de cada producto
print("4. Proporción de ventas:")
total = sales["Ventas"].sum()
product_pct = sales.groupby("Producto")["Ventas"].sum() / total * 100
print(product_pct.round(2))
Otras extensionesgroupby es una operación central en el análisis de datos; dominarla permite realizar de manera eficiente diversas tareas de análisis estadístico.