Python-Pandas Wie ordne ich Groupby-Operations-Ergebnisse den Spalten im übergeordneten Datenrahmen zu?
Ich habe den folgenden Datenrahmen in IPython, in dem jede Zeile ein einzelner Bestand ist:
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)
Ich möchte eine Groupby-Operation anwenden, die die kapitalgewichtete durchschnittliche Rendite für alle Daten in der Spalte "Jahrmonat" berechnet.
Das funktioniert wie erwartet:
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
Aber dann möchte ich diese Werte sozusagen an die Indizes im ursprünglichen Datenrahmen zurücksenden und sie als konstante Spalten speichern, in denen die Daten übereinstimmen.
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
Mir ist klar, dass diese naive Aufgabe nicht funktionieren sollte. Aber was ist das "richtige" Pandas-Idiom, um das Ergebnis einer groupby-Operation in eine neue Spalte im übergeordneten Datenrahmen zuzuweisen?
Am Ende möchte ich eine Spalte mit dem Namen "MarketReturn", die ein sich wiederholender konstanter Wert für alle Indizes ist, deren Datum mit der Ausgabe der groupby-Operation übereinstimmt.
Ein Hack, um dies zu erreichen, wäre der folgende:
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]
Aber das ist langsam, schlecht und unpythonisch.