Python Pandas ¿Cómo asignar los resultados de la operación grupal a las columnas en el marco de datos principal?
Tengo el siguiente marco de datos en IPython, donde cada fila es un stock único:
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 calcula el rendimiento promedio ponderado por límite en todo, por cada fecha en la columna "año mes".
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 ordenar "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 lenguaje Pandas "correcto" para asignar el resultado de una operación groupby a 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 tengan fecha coincidente con la salida de la operación groupby.
Un truco para lograrlo 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 antipónico.