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.

Antworten auf die Frage(5)

Ihre Antwort auf die Frage