Python Pandas Jak przypisać wyniki operacji Groupby do kolumn w macierzystej ramce danych?
Mam w IPythonie następującą ramkę danych, gdzie każdy wiersz to pojedynczy zapas:
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)
Chcę zastosować operację grupowania, która oblicza średnią ważoną stopę zwrotu we wszystkich punktach na każdą datę w kolumnie „yearmonth”.
Działa to zgodnie z oczekiwaniami:
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
Ale potem chcę posortować te wartości z powrotem do indeksów w oryginalnej ramce danych i zapisać je jako stałe kolumny, w których daty się zgadzają.
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
Zdaję sobie sprawę, że to naiwne zadanie nie powinno działać. Ale jaki jest „właściwy” idiom Pand do przypisywania wyniku operacji Groupby do nowej kolumny nadrzędnej ramki danych?
Na koniec chcę, aby kolumna o nazwie „MarketReturn” była powtarzaną stałą wartością dla wszystkich indeksów, które mają datę pasującą do wyniku operacji groupby.
Jeden hack do osiągnięcia tego celu to:
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]
Ale to jest powolne, złe i niepythoniczne.