Tengo el siguiente marco de datos en IPython, donde cada fila es una sola acción:
In [261]: bdata
Out[261]:
<class 'pandas.core.frame.DataFrame'>
Int64Index: 21210 entries, 0 to 21209
Data columns:
BloombergTicker 21206 non-null values
Company 21210 non-null values
Country 21210 non-null values
MarketCap 21210 non-null values
PriceReturn 21210 non-null values
SEDOL 21210 non-null values
yearmonth 21210 non-null values
dtypes: float64(2), int64(1), object(4)
Quiero aplicar una operación groupby que calcule el rendimiento promedio ponderado por capitalización en todo, por cada fecha en la columna "yearmonth".
Esto funciona como se esperaba:
In [262]: bdata.groupby("yearmonth").apply(lambda x: (x["PriceReturn"]*x["MarketCap"]/x["MarketCap"].sum()).sum())
Out[262]:
yearmonth
201204 -0.109444
201205 -0.290546
Pero luego quiero "transmitir" estos valores a los índices en el marco de datos original y guardarlos como columnas constantes donde coinciden las fechas.
In [263]: dateGrps = bdata.groupby("yearmonth")
In [264]: dateGrps["MarketReturn"] = dateGrps.apply(lambda x: (x["PriceReturn"]*x["MarketCap"]/x["MarketCap"].sum()).sum())
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
/mnt/bos-devrnd04/usr6/home/espears/ws/Research/Projects/python-util/src/util/<ipython-input-264-4a68c8782426> in <module>()
----> 1 dateGrps["MarketReturn"] = dateGrps.apply(lambda x: (x["PriceReturn"]*x["MarketCap"]/x["MarketCap"].sum()).sum())
TypeError: 'DataFrameGroupBy' object does not support item assignment
Me doy cuenta de que esta ingenua tarea no debería funcionar. Pero, ¿cuál es el idioma "correcto" de Pandas para asignar el resultado de una operación groupby en una nueva columna en el marco de datos principal?
Al final, quiero una columna llamada "MarketReturn" que será un valor constante repetido para todos los índices que tienen una fecha coincidente con la salida de la operación groupby.
Un truco para lograr esto sería el siguiente:
marketRetsByDate = dateGrps.apply(lambda x: (x["PriceReturn"]*x["MarketCap"]/x["MarketCap"].sum()).sum())
bdata["MarketReturn"] = np.repeat(np.NaN, len(bdata))
for elem in marketRetsByDate.index.values:
bdata["MarketReturn"][bdata["yearmonth"]==elem] = marketRetsByDate.ix[elem]
Pero esto es lento, malo y poco pítico.