J'ai le cadre de données suivant dans IPython, où chaque ligne est une action unique :
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)
Je veux appliquer une opération groupby qui calcule le rendement moyen pondéré par les capitalisations pour tout, pour chaque date dans la colonne "année-mois".
Cela fonctionne comme prévu :
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
Mais ensuite, je veux en quelque sorte "diffuser" ces valeurs vers les indices du cadre de données d'origine, et les enregistrer en tant que colonnes constantes lorsque les dates correspondent.
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
Je réalise que cette mission naïve ne devrait pas fonctionner. Mais quel est le "bon" idiome Pandas pour affecter le résultat d'une opération groupby dans une nouvelle colonne du cadre de données parent ?
Au final, je veux une colonne appelée "MarketReturn" qui sera une valeur constante répétée pour tous les indices qui ont une date correspondante avec la sortie de l'opération groupby.
Un moyen d'y parvenir serait le suivant :
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]
Mais c'est lent, mauvais, et non pythique.