Python 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을 재구조화 해보겠습니다.

 

 

reshaping pandas DataFrame with MultiIndex Column by Stacking

 

(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
0.00MB

## 참고로, 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

 

 

이번 포스팅이 많은 도움이 되었기를 바랍니다. 

행복한 데이터 과학자 되세요! :-)

 

728x90
반응형
Posted by Rfriend
,