Ich habe den folgenden Datenrahmen in IPython, wobei 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 jedes Datum in der Spalte "Jahrmonat" berechnet.
Dies 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 zurück zu den Indizes im ursprünglichen Datenrahmen "senden" 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 die "richtige" Pandas-Sprache, um das Ergebnis einer Groupby-Operation einer neuen Spalte im übergeordneten Datenrahmen zuzuweisen?
Am Ende möchte ich eine Spalte mit dem Namen "MarketReturn", die ein wiederholter 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.