Python Pandas 연산 결과를 상위 데이터 프레임의 열에 다시 할당하는 방법은 무엇입니까?
IPython에는 다음과 같은 데이터 프레임이 있습니다. 각 행은 하나의 스톡입니다.
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)
"년월" 열의 각 날짜마다 모든 항목에 걸쳐 상한 가중치 평균 수익률을 계산하는 작업별 그룹을 적용하고자 합니다.
예상대로 작동합니다.
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
그런 다음 이 값들을 원래 데이터 프레임의 인덱스로 다시 "브로드캐스트"한 다음 날짜가 일치하는 일정한 열로 저장하고자 합니다.
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
저는 이 순진한 과제가 효과가 있어서는 안 된다는 것을 알고 있습니다.그러나 조작에 의한 그룹의 결과를 상위 데이터 프레임의 새 열에 할당하는 "올바른" 판다 관용어는 무엇일까요?
결국 연산별 그룹의 출력과 날짜가 일치하는 모든 지수에 대해 반복되는 상수 값이 되는 "MarketReturn"이라는 열을 원합니다.
이를 달성하기 위한 한 번의 해킹은 다음과 같습니다.
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]
하지만 이것은 느리고 나쁘고 파이토닉적이지 않습니다.
In [97]: df = pandas.DataFrame({'month': np.random.randint(0,11, 100), 'A': np.random.randn(100), 'B': np.random.randn(100)})
In [98]: df.join(df.groupby('month')['A'].sum(), on='month', rsuffix='_r')
Out[98]:
A B month A_r
0 -0.040710 0.182269 0 -0.331816
1 -0.004867 0.642243 1 2.448232
2 -0.162191 0.442338 4 2.045909
3 -0.979875 1.367018 5 -2.736399
4 -1.126198 0.338946 5 -2.736399
5 -0.992209 -1.343258 1 2.448232
6 -1.450310 0.021290 0 -0.331816
7 -0.675345 -1.359915 9 2.722156
내가 아직도 엄청나게 똑똑한 방법을 연구하는 동안apply
지정된 조각을 연결합니다. 다음은 작업별 그룹 후 상위에 새 열을 추가하는 다른 방법입니다.
In [236]: df
Out[236]:
yearmonth return
0 201202 0.922132
1 201202 0.220270
2 201202 0.228856
3 201203 0.277170
4 201203 0.747347
In [237]: def add_mkt_return(grp):
.....: grp['mkt_return'] = grp['return'].sum()
.....: return grp
.....:
In [238]: df.groupby('yearmonth').apply(add_mkt_return)
Out[238]:
yearmonth return mkt_return
0 201202 0.922132 1.371258
1 201202 0.220270 1.371258
2 201202 0.228856 1.371258
3 201203 0.277170 1.024516
4 201203 0.747347 1.024516
일반적으로 groupby()를 사용할 때 .transform() 함수 panda를 사용하면 원래와 같은 길이의 테이블이 반환됩니다..sum() 또는 .first()와 같은 다른 함수를 사용하면 각 행이 그룹인 테이블이 반환됩니다.
이것이 어떻게 적용되는지는 잘 모르겠지만 정교한 람다 함수를 변환으로 구현하는 것은 상당히 까다로울 수 있기 때문에 가장 도움이 되는 전략은 필요한 변수를 생성하고 원래 데이터 세트에 배치한 다음 작업을 수행하는 것입니다.
먼저 올바르게 수행하려는 작업을 이해하면 각 그룹의 총 시가총액을 계산할 수 있습니다.
bdata['group_MarketCap'] = bdata.groupby('yearmonth')['MarketCap'].transform('sum')
이렇게 하면 각 그룹별 시가총액의 합계를 포함하는 원래 데이터에 "group_MarketCap"이라는 열이 추가됩니다.그런 다음 가중치를 직접 계산할 수 있습니다.
bdata['weighted_P'] = bdata['PriceReturn'] * (bdata['MarketCap']/bdata['group_MarketCap'])
그리고 마지막으로 동일한 변환 함수를 사용하여 각 그룹에 대한 가중 평균을 계산합니다.
bdata['MarketReturn'] = bdata.groupby('yearmonth')['weighted_P'].transform('sum')
저는 변수를 이런 식으로 만드는 경향이 있습니다.때로는 하나의 명령어로 모든 것을 처리할 수 있지만, 대부분의 경우 팬더가 전체 데이터 세트 스케일에서 작동하려면 새 개체를 인스턴스화해야 하기 때문에(즉, 하나가 아직 존재하지 않으면 두 개의 열을 함께 추가할 수 없음) groupby()에서 항상 작동하지는 않습니다.
도움이 되길 바라요 :)
요를 ?transform
메소드(대신 aggregate)?원래 예에서 사용한다면 원하는 대로 (방송) 할 수 있습니다.
원래 데이터 프레임에 할당할 방법을 찾지 못했습니다.그래서 저는 그룹의 결과를 저장하고 연결합니다.그런 다음 연결된 데이터 프레임을 인덱스별로 정렬하여 원래 순서를 입력 데이터 프레임으로 얻습니다.다음은 샘플 코드입니다.
In [10]: df = pd.DataFrame({'month': np.random.randint(0,11, 100), 'A': np.random.randn(100), 'B': np.random.randn(100)})
In [11]: df.head()
Out[11]:
month A B
0 4 -0.029106 -0.904648
1 2 -2.724073 0.492751
2 7 0.732403 0.689530
3 2 0.487685 -1.017337
4 1 1.160858 -0.025232
In [12]: res = []
In [13]: for month, group in df.groupby('month'):
...: new_df = pd.DataFrame({
...: 'A^2+B': group.A ** 2 + group.B,
...: 'A+B^2': group.A + group.B**2
...: })
...: res.append(new_df)
...:
In [14]: res = pd.concat(res).sort_index()
In [15]: res.head()
Out[15]:
A^2+B A+B^2
0 -0.903801 0.789282
1 7.913327 -2.481270
2 1.225944 1.207855
3 -0.779501 1.522660
4 1.322360 1.161495
이 방법은 상당히 빠르고 확장 가능합니다.여기서 모든 특징을 도출할 수 있습니다.
참고: 데이터 프레임이 너무 크면,
concat
MMO 오류를 유발할 수 있습니다.
언급URL : https://stackoverflow.com/questions/12200693/python-pandas-how-to-assign-groupby-operation-results-back-to-columns-in-parent
'source' 카테고리의 다른 글
jQuery 대화 상자 단추에 CSS 적용 (0) | 2023.09.21 |
---|---|
.jar로의 Spring Boot 패키지 웹 응용 프로그램 (0) | 2023.09.21 |
Woocommerce의 특정 제품 속성 값에 대한 모든 제품 변형 가져오기 (0) | 2023.09.21 |
uppload_files true이지만 edit_post false로 사용자 지정 사용자 역할을 워드프레스합니다. 미디어를 삭제하고 편집하려면 어떻게 해야 합니까? (0) | 2023.09.21 |
if/-then-else 문에 행을 삽입하는 중 (0) | 2023.09.21 |