Es posible devolver cualquier número de valores agregados de un objeto groupby con apply. Simplemente, devuelva una Serie y los valores del índice se convertirán en los nuevos nombres de columna.
Veamos un ejemplo rápido:
df = pd.DataFrame({'group':['a','a','b','b'],
'd1':[5,10,100,30],
'd2':[7,1,3,20],
'weights':[.2,.8, .4, .6]},
columns=['group', 'd1', 'd2', 'weights'])
df
group d1 d2 weights
0 a 5 7 0.2
1 a 10 1 0.8
2 b 100 3 0.4
3 b 30 20 0.6
Defina una función personalizada a la que se le pasará apply. Acepta implícitamente un DataFrame, lo que significa que el dataparámetro es un DataFrame. Observe cómo usa múltiples columnas, lo cual no es posible con el aggmétodo groupby:
def weighted_average(data):
d = {}
d['d1_wa'] = np.average(data['d1'], weights=data['weights'])
d['d2_wa'] = np.average(data['d2'], weights=data['weights'])
return pd.Series(d)
Llame al applymétodo groupby con nuestra función personalizada:
df.groupby('group').apply(weighted_average)
d1_wa d2_wa
group
a 9.0 2.2
b 58.0 13.2
Puede obtener un mejor rendimiento calculando previamente los totales ponderados en nuevas columnas DataFrame como se explica en otras respuestas y evitar el uso por applycompleto.