[Python pandas] MultiIndex Column 의 DataFrame 을 Column Level 기준으로 Stacking 해서 재구조화 하기
Python 분석과 프로그래밍/Python 데이터 전처리 2021. 8. 30. 23:57Python pandas의 DataFrame은 특이하고 재미있게도 두 개 이상의 MultiIndex Column 을 가지는 DataFrame 도 지원합니다. R의 DataFrame 이나 DB의 Table 에서는 칼럼이라고 하면 당연히 1개 layer의 칼럼들만을 지원하기에, Python pandas의 2개 이상 layer의 칼럼들을 가진 DataFrame 이 처음에는 생소하고 재미있게 보였습니다.
이번 포스팅에서는 Python pandas DataFrame 중에서 두 개의 MultiIndex Column 을 가지는 DataFrame 에 대해서, 이중 한개 layer의 칼럼을 기준으로 Stacking을 해서 wide-format 을 long-format으로 DataFrame을 재구조화 해보겠습니다.
(1) csv 파일을 읽어와서 MultiIndex Column을 가진 pandas DataFrame 으로 만들기
(2) MultiIndex Column 의 Level에 이름 부여하기
(3) MultiIndex Column DataFrame의 특정 Level을 Stacking 해서 Long-format 으로 재구조화 하기
(4) 재구조화한 DataFrame의 Index 를 칼럼으로 재설정하고 정렬하기
위의 순서대로 간단한 샘플 데이터를 가지고 예를 들어보겠습니다.
(1) csv 파일을 읽어와서 MultiIndex Column을 가진 pandas DataFrame 으로 만들기
아래에 첨부한 dataset.csv 파일을 pandas 의 read_csv() 메소드로 csv 파일을 읽어와서 DataFrame으로 만들 때 header=[0, 1] 옵션을 지정해줌으로써 ==> 첫번째와 두번째 행을 MultiIndex Column 으로 해서 DataFrame을 만들 수 있습니다.
## 참고로, dataset.csv 파일에는 아래 샘플 데이터가 들어있습니다.
g1,g1,g1,g2,g2,g2
c1,c2,c3,c1,c2,c3
1,2,3,4,5,6
7,8,9,10,11,12
13,14,15,16,17,18
import pandas as pd
## reading csv file with multi-column index
df = pd.read_csv('dataset.csv', header=[0, 1])
print(df)
# g1 g2
# c1 c2 c3 c1 c2 c3
# 0 1 2 3 4 5 6
# 1 7 8 9 10 11 12
# 2 13 14 15 16 17 18
## MultiIndex Columns
df.columns
# MultiIndex([('g1', 'c1'),
# ('g1', 'c2'),
# ('g1', 'c3'),
# ('g2', 'c1'),
# ('g2', 'c2'),
# ('g2', 'c3')],
# )
(2) MultiIndex Column 의 Level에 이름 부여하기
MultiIndex Column의 Level 에 접근할 때 "위치(position)"로 할 수도 있고, 혹은 Level에 이름을 부여(rename)해서 "이름(name)"을 기준으로 접근할 수도 있습니다.
rename() 메소드를 사용해서 이번 예제의 MultiIndex Column의 첫번째 Level에는 'grp_nm' 이라는 이름을, 두번째 Level 에는 'col_nm' 이라는 이름을 부여해보겠습니다.
## renaming multi-column index
df.columns.rename(['grp_nm', 'col_nm'], inplace=True)
print(df)
# grp_nm g1 g2
# col_nm c1 c2 c3 c1 c2 c3
# 0 1 2 3 4 5 6
# 1 7 8 9 10 11 12
# 2 13 14 15 16 17 18
df.columns
# MultiIndex([('g1', 'c1'),
# ('g1', 'c2'),
# ('g1', 'c3'),
# ('g2', 'c1'),
# ('g2', 'c2'),
# ('g2', 'c3')],
# names=['grp_nm', 'col_nm']) # <== now, names of MultiIndex levels
(3) MultiIndex Column DataFrame의 특정 Level을 Stacking 해서 Long-format 으로 재구조화 하기
위의 (2)번에서 MultiIndex Column의 첫번째 Level 에 'grp_nm' 이라는 이름을 부여했는데요, 이번에는 'grp_nm' 이름의 Level 을 기준으로 stack() 메소드를 사용해서 wide-format 을 long-format 의 DataFrame으로 재구조화(reshaping) 해보겠습니다.
이렇게 stacking을 해서 재구조화하면 MultiIndex Column DataFrame 이 (우리가 익숙하게 사용하는) SingleIndex Column의 DataFrame으로 바뀌게 되며, ==> 이제 'grp_nm'은 Index 로 들어가 있습니다.
## reshaping DataFrame from MultiIndex Column from SingleIndex long-format by stacking
df_stacked = df.stack(level='grp_nm')
print(df_stacked)
# col_nm c1 c2 c3
# grp_nm
# 0 g1 1 2 3
# g2 4 5 6
# 1 g1 7 8 9
# g2 10 11 12
# 2 g1 13 14 15
# g2 16 17 18
(4) 재구조화한 DataFrame의 Index 를 칼럼으로 재설정하고 정렬하기
마지막으로, MultiIndex Column 의 첫번째 Level 을 Stacking 하고 난 후 Index로 사용된 'grp_nm' 을 reset_index() 메소드를 사용해서 칼럼으로 재설정하고, ==> 가시성을 높일 수 있도록 sort_values(by=['grp_nm']) 을 사용해서 'grp_nm' 칼럼을 기준으로 오름차순 정렬을 해보겠습니다.
## reset index and sorting by column
df_stacked_sorted = df.stack(level='grp_nm').reset_index(['grp_nm']).sort_values(by=['grp_nm'])
print(df_stacked_sorted)
# col_nm grp_nm c1 c2 c3
# 0 g1 1 2 3
# 1 g1 7 8 9
# 2 g1 13 14 15
# 0 g2 4 5 6
# 1 g2 10 11 12
# 2 g2 16 17 18
이번 포스팅이 많은 도움이 되었기를 바랍니다.
행복한 데이터 과학자 되세요! :-)