Groupby¶
Groupby es un concepto bastante simple. Podemos crear una agrupación de categorías y aplicar una función a las categorías.
El proceso de groupby se puede resumiren los siguientes pasos:
- División: es un proceso en el que dividimos los datos en grupos aplicando algunas condiciones en los conjuntos de datos.
- Aplicación: es un proceso en el que aplicamos una función a cada grupo de forma independiente
- Combinación: es un proceso en el que combinamos diferentes conjuntos de datos después de aplicar groupby y resultados en una estructura de datos
Después de dividir los datos en un grupo, aplicamos una función a cada grupo para realizar algunas operaciones que son:
- Agregación: es un proceso en el que calculamos una estadística resumida (o estadística) sobre cada grupo. Por ejemplo, Calcular sumas de grupo o medios
- Transformación: es un proceso en el que realizamos algunos cálculos específicos del grupo y devolvemos un índice similar. Por ejemplo, llenar NA dentro de grupos con un valor derivado de cada grupo
- Filtración: es un proceso en el cual descartamos algunos grupos, de acuerdo con un cálculo grupal que evalúa Verdadero o Falso. Por ejemplo, Filtrar datos en función de la suma o media grupal
Agrupar por una columna¶
Supongamos que tenemos un conjunto de datos de ventas de productos y queremos agruparlos por la columna "Producto". El siguiente código nos permitirá hacerlo:
import pandas as pd
# Crear un DataFrame de ejemplo
datos = {
'Producto': ['A', 'B', 'A', 'B', 'A', 'B', 'A', 'B'],
'Mes': ['Enero', 'Enero','Enero', 'Enero', 'Febrero', 'Febrero','Febrero', 'Febrero'],
'Ventas': [100, 200, 150, 250, 300, 350, 400, 450]
}
df = pd.DataFrame(datos).sort_values(['Producto'])
df
Producto | Mes | Ventas | |
---|---|---|---|
0 | A | Enero | 100 |
2 | A | Enero | 150 |
4 | A | Febrero | 300 |
6 | A | Febrero | 400 |
1 | B | Enero | 200 |
3 | B | Enero | 250 |
5 | B | Febrero | 350 |
7 | B | Febrero | 450 |
# Agrupar por Producto y calcular la suma de las ventas en cada grupo
agrupado = df.groupby('Producto')['Ventas'].sum()
agrupado
Producto A 950 B 1250 Name: Ventas, dtype: int64
Agrupar por varias columnas¶
En este ejemplo, supongamos que queremos agrupar los datos por dos columnas: "Producto" y "Mes". El siguiente código nos permitirá hacerlo:
# Agrupar por Producto y Mes y calcular la suma de las ventas en cada grupo
agrupado = df.groupby(['Producto', 'Mes'])['Ventas'].sum()
agrupado
Producto Mes A Enero 250 Febrero 700 B Enero 450 Febrero 800 Name: Ventas, dtype: int64
Aplicar múltiples funciones a cada grupo¶
En este ejemplo, supongamos que queremos calcular la suma y el promedio de las ventas en cada grupo. El siguiente código nos permitirá hacerlo:
# Agrupar por Producto y Mes y calcular la suma y promedio de las ventas en cada grupo
agrupado = df.groupby(['Producto', 'Mes']).agg({'Ventas': ['sum', 'mean']})
agrupado
Ventas | |||
---|---|---|---|
sum | mean | ||
Producto | Mes | ||
A | Enero | 250 | 125.0 |
Febrero | 700 | 350.0 | |
B | Enero | 450 | 225.0 |
Febrero | 800 | 400.0 |
Groupby Apply¶
Este método permite aplicar una función a cada grupo y devolver un DataFrame con el resultado.
df.groupby(columnas_a_agrupar).apply(funcion)
Supongamos que tenemos un DataFrame con información sobre ventas de diferentes productos en diferentes regiones:
import pandas as pd
data = {
'Region': ['North', 'North', 'South', 'South', 'East', 'West', 'East', 'West'],
'Product': ['A', 'B', 'A', 'B', 'A', 'B', 'A', 'B'],
'Sales': [100, 200, 150, 250, 120, 180, 110, 190]
}
df = pd.DataFrame(data)
df
Region | Product | Sales | |
---|---|---|---|
0 | North | A | 100 |
1 | North | B | 200 |
2 | South | A | 150 |
3 | South | B | 250 |
4 | East | A | 120 |
5 | West | B | 180 |
6 | East | A | 110 |
7 | West | B | 190 |
Podemos usar groupby()
para agrupar los datos por región y aplicar una función personalizada que calcule el porcentaje de ventas de cada producto en cada región:
def porcentaje_ventas_grupo(grupo):
grupo['Porcentaje_Ventas'] = grupo['Sales'] / grupo['Sales'].sum()
return grupo
df.groupby('Region').apply(porcentaje_ventas_grupo)
C:\Users\franc\AppData\Local\Temp\ipykernel_2644\1199783526.py:5: DeprecationWarning: DataFrameGroupBy.apply operated on the grouping columns. This behavior is deprecated, and in a future version of pandas the grouping columns will be excluded from the operation. Either pass `include_groups=False` to exclude the groupings or explicitly select the grouping columns after groupby to silence this warning. df.groupby('Region').apply(porcentaje_ventas_grupo)
Region | Product | Sales | Porcentaje_Ventas | ||
---|---|---|---|---|---|
Region | |||||
East | 4 | East | A | 120 | 0.521739 |
6 | East | A | 110 | 0.478261 | |
North | 0 | North | A | 100 | 0.333333 |
1 | North | B | 200 | 0.666667 | |
South | 2 | South | A | 150 | 0.375000 |
3 | South | B | 250 | 0.625000 | |
West | 5 | West | B | 180 | 0.486486 |
7 | West | B | 190 | 0.513514 |
En este ejemplo, hemos definido una función personalizada porcentaje_ventas_grupo
que toma como argumento un grupo de datos y calcula el porcentaje de ventas de cada producto en ese grupo. Después, hemos aplicado esta función a cada grupo usando el método apply()
.
Groupby Transform¶
En pandas, el método transform()
permite aplicar una función de transformación a cada grupo de un objeto groupby. La función de transformación se aplica a cada grupo y el resultado se asigna de vuelta a las filas correspondientes en el DataFrame original.
Para el ejemplo anterior, podemos usar groupby()
para agrupar los datos por región y aplicar una función de transformación que calcule el promedio de ventas de cada producto en cada región y lo añada como una nueva columna en el DataFrame original:
df['Promedio_Ventas'] = df.groupby('Region')['Sales'].transform('mean')
df
Region | Product | Sales | Promedio_Ventas | |
---|---|---|---|---|
0 | North | A | 100 | 150.0 |
1 | North | B | 200 | 150.0 |
2 | South | A | 150 | 200.0 |
3 | South | B | 250 | 200.0 |
4 | East | A | 120 | 115.0 |
5 | West | B | 180 | 185.0 |
6 | East | A | 110 | 115.0 |
7 | West | B | 190 | 185.0 |
En este ejemplo, hemos usado el método transform()
para calcular el promedio de ventas de cada producto en cada región y lo hemos asignado como una nueva columna llamada "Promedio_Ventas" en el DataFrame original. La función de transformación que hemos usado es mean()
, que calcula la media de las ventas en cada grupo.
Groupby Filter¶
En pandas, el método groupby()
se puede combinar con el método filter()
para filtrar filas de un DataFrame según ciertas condiciones aplicadas a los grupos de un objeto groupby. filter()
devuelve un nuevo DataFrame que contiene las filas que cumplen las condiciones especificadas para cada grupo.
Para el ejemplo anterior, podemos usar groupby()
para agrupar los datos por región y luego usar filter()
para seleccionar los grupos que tienen un promedio de ventas mayor que 150:
df_filtered = df.groupby('Region').filter(lambda x: x['Sales'].mean() > 150)
df_filtered
Region | Product | Sales | Promedio_Ventas | |
---|---|---|---|---|
2 | South | A | 150 | 200.0 |
3 | South | B | 250 | 200.0 |
5 | West | B | 180 | 185.0 |
7 | West | B | 190 | 185.0 |
En este ejemplo, hemos usado la función lambda lambda x: x['Sales'].mean() > 150
como condición para filtrar los grupos. Esta función lambda devuelve True si el promedio de ventas en el grupo x
es mayor que 150 y False en caso contrario. El método filter()
devuelve un nuevo DataFrame que contiene solo las filas de los grupos que cumplen esta condición.
Observación: Para iterar a través de los grupos generados por el método groupby()
de Pandas, se puede usar un bucle for
. En cada iteración, se obtiene una tupla (nombre_grupo, subconjunto_datos)
donde nombre_grupo
es el nombre del grupo y subconjunto_datos
es un objeto DataFrame que contiene solo las filas que pertenecen a ese grupo.
En el ejemplo anterior, podemos agrupar los datos por región y luego iterar a través de los grupos usando un bucle for
:
for region, data in df.groupby('Region'):
print(region)
print(data)
print('--------------')
East Region Product Sales Promedio_Ventas 4 East A 120 115.0 6 East A 110 115.0 -------------- North Region Product Sales Promedio_Ventas 0 North A 100 150.0 1 North B 200 150.0 -------------- South Region Product Sales Promedio_Ventas 2 South A 150 200.0 3 South B 250 200.0 -------------- West Region Product Sales Promedio_Ventas 5 West B 180 185.0 7 West B 190 185.0 --------------