¿Cómo calcular vwap (precio promedio ponderado por volumen) utilizando groupby y aplicar?

He leído varias publicaciones similares a mi pregunta, pero todavía no puedo entenderlo. Tengo un df pandas que se parece a lo siguiente (durante varios días):

Out[1]: price quantity time 2016-06-08 09:00:22 32.30 1960.0 2016-06-08 09:00:22 32.30 142.0 2016-06-08 09:00:22 32.30 3857.0 2016-06-08 09:00:22 32.30 1000.0 2016-06-08 09:00:22 32.35 991.0 2016-06-08 09:00:22 32.30 447.0 ... 

Para calcular el vwap podría hacer:

 df['vwap'] = (np.cumsum(df.quantity * df.price) / np.cumsum(df.quantity)) 

Sin embargo, me gustaría volver a empezar todos los días (groupby), pero no puedo averiguar cómo hacer que funcione con una función (lambda?).

 df['vwap_day'] = df.groupby(df.index.date)['vwap'].apply(lambda ... 

La velocidad es esencial. Agradecería cualquier ayuda 🙂

Opción 0
enfoque de vainilla simple

 def vwap(df): q = df.quantity.values p = df.price.values return df.assign(vwap=(p * q).cumsum() / q.cumsum()) df = df.groupby(df.index.date, group_keys=False).apply(vwap) df price quantity vwap time 2016-06-08 09:00:22 32.30 1960.0 32.300000 2016-06-08 09:00:22 32.30 142.0 32.300000 2016-06-08 09:00:22 32.30 3857.0 32.300000 2016-06-08 09:00:22 32.30 1000.0 32.300000 2016-06-08 09:00:22 32.35 991.0 32.306233 2016-06-08 09:00:22 32.30 447.0 32.305901 

Opción 1
Tirando un poco de eval

 df = df.assign( vwap=df.eval( 'wgtd = price * quantity', inplace=False ).groupby(df.index.date).cumsum().eval('wgtd / quantity') ) df price quantity vwap time 2016-06-08 09:00:22 32.30 1960.0 32.300000 2016-06-08 09:00:22 32.30 142.0 32.300000 2016-06-08 09:00:22 32.30 3857.0 32.300000 2016-06-08 09:00:22 32.30 1000.0 32.300000 2016-06-08 09:00:22 32.35 991.0 32.306233 2016-06-08 09:00:22 32.30 447.0 32.305901