Python/Python Pandas

Python Pandas : Multi index 없애기, 다중 column 없애기, multi column 없애기

CosmosProject 2023. 10. 24. 23:53
728x90
반응형

 

 

 

Pandas를 통해서 데이터를 다루다 보면 간혹 multi index가 생기는 경우가 있습니다.

특히 pivot_table() method를 사용한 후에 자주 발생하는데 이런 경우는 사실 다루기가 마냥 좋은 상태는 아닙니다.

 

 

 

import pandas as pd

multi_cols = pd.MultiIndex.from_tuples(
    [
        ('number', 'date'),
        ('number', 'item'),
        ('string', 'item_name')
    ]
)

df_test = pd.DataFrame(
    [
        (20230101, 1, 'a'),
        (20230101, 2, 'b'),
        (20230101, 3, 'c'),

        (20230102, 1, 'a'),
        (20230102, 3, 'c'),

        (20230103, 2, 'b'),
        (20230103, 4, 'd'),
    ],
    columns=multi_cols
)

print(df_test)



-- Result
     number         string
       date item item_name
0  20230101    1         a
1  20230101    2         b
2  20230101    3         c
3  20230102    1         a
4  20230102    3         c
5  20230103    2         b
6  20230103    4         d

 

multi index가 무엇인지 모르는 분들을 위해 multi index를 가진 DataFrame을 만들어봤습니다.

 

위 예시의 결과를 보면 column 이름을 표시하는 부분이 2줄로 되어있는 것을 알 수 있습니다.

 

     number         string
       date item item_name

이렇게 column name이 두줄로 표시되어 있습니다.

어쨌든 DataFrame의 최종 column 개수는 3개인데 각 column의 표시가 2중으로 되어있다는 것이죠.

 

실제 이론상 2중, 3중, 4중, ... 등등의 column name 표시가 가능합니다.

 

이런 상태를 multi index 또는 multi column이라고 합니다.

 

 

import pandas as pd

multi_cols = pd.MultiIndex.from_tuples(
    [
        ('number', 'date'),
        ('number', 'item'),
        ('string', 'item_name')
    ]
)

df_test = pd.DataFrame(
    [
        (20230101, 1, 'a'),
        (20230101, 2, 'b'),
        (20230101, 3, 'c'),

        (20230102, 1, 'a'),
        (20230102, 3, 'c'),

        (20230103, 2, 'b'),
        (20230103, 4, 'd'),
    ],
    columns=multi_cols
)

print(df_test.columns)



-- Result
MultiIndex([('number',      'date'),
            ('number',      'item'),
            ('string', 'item_name')],
           )

 

그래서 이런 multi index DataFrame의 columns를 print해보면 위처럼 하나의 column에 대해 2개의 index가 tuple로 묶인 채로 표시됩니다.

 

 

이런 경우에 multi index를 없애고 single index로 만들면 다루기 더 쉬워지는 경우가 있습니다.

 

위같은 multi index를 없애는 방법은 여러 가지가 있는데 그 중 몇가지만 알아봅시다.

 

 

 

import pandas as pd

multi_cols = pd.MultiIndex.from_tuples(
    [
        ('number', 'date'),
        ('number', 'item'),
        ('string', 'item_name')
    ]
)

df_test = pd.DataFrame(
    [
        (20230101, 1, 'a'),
        (20230101, 2, 'b'),
        (20230101, 3, 'c'),

        (20230102, 1, 'a'),
        (20230102, 3, 'c'),

        (20230103, 2, 'b'),
        (20230103, 4, 'd'),
    ],
    columns=multi_cols
)


df_test = df_test.droplevel(level=0, axis=1)
print(df_test)



-- Result
       date  item item_name
0  20230101     1         a
1  20230101     2         b
2  20230101     3         c
3  20230102     1         a
4  20230102     3         c
5  20230103     2         b
6  20230103     4         d

 

droplevel() method를 사용하는 예시입니다.

 

결과부터 보면 각 column의 이름이 1줄로만 표시되는 것을 볼 수 있죠.

 

 

 

df_test = df_test.droplevel(level=0, axis=1)

핵심은 이 부분입니다.

droplevel()은 이름에서도 볼 수 있듯이 level (계층)을 drop하는 기능을 합니다.

 

여기서 level=0이라고 명시했는데

 

     number         string --> level 0 index
       date item item_name --> level 1 index

이러한 multi index에서 더 위쪽에 있는 것이 level = 0이고

더 아래에 갈수록 level이 커집니다.

 

따라서 droplevel()에서 level=0으로 적었다는 것은 위쪽에 있는 level 0 index를 없애겠다는 의미입니다.

 

그래서 결과에는 date, item, item_name 3개의 column name만 남은 것을 볼 수 있죠.

 

 

 

 

import pandas as pd

multi_cols = pd.MultiIndex.from_tuples(
    [
        ('number', 'date'),
        ('number', 'item'),
        ('string', 'item_name')
    ]
)

df_test = pd.DataFrame(
    [
        (20230101, 1, 'a'),
        (20230101, 2, 'b'),
        (20230101, 3, 'c'),

        (20230102, 1, 'a'),
        (20230102, 3, 'c'),

        (20230103, 2, 'b'),
        (20230103, 4, 'd'),
    ],
    columns=multi_cols
)


df_test = df_test.droplevel(level=1, axis=1)
print(df_test)



-- Result
     number  number string
0  20230101       1      a
1  20230101       2      b
2  20230101       3      c
3  20230102       1      a
4  20230102       3      c
5  20230103       2      b
6  20230103       4      d

 

반대로 level=1로 명시할 경우 아래쪽 줄에 있던 column name이 다 사라지고 위쪽(level=0)에 있던 column name만 남은 것을 알 수 있습니다.

 

 

 

 

 

 

 

import pandas as pd

multi_cols = pd.MultiIndex.from_tuples(
    [
        ('number', 'date'),
        ('number', 'item'),
        ('string', 'item_name')
    ]
)

df_test = pd.DataFrame(
    [
        (20230101, 1, 'a'),
        (20230101, 2, 'b'),
        (20230101, 3, 'c'),

        (20230102, 1, 'a'),
        (20230102, 3, 'c'),

        (20230103, 2, 'b'),
        (20230103, 4, 'd'),
    ],
    columns=multi_cols
)

print(df_test.columns)
print(df_test.columns.droplevel(level=0))


df_test.columns = df_test.columns.droplevel(level=0)

print(df_test)



-- Result
MultiIndex([('number',      'date'),
            ('number',      'item'),
            ('string', 'item_name')],
           )
           
Index(['date', 'item', 'item_name'], dtype='object')

       date  item item_name
0  20230101     1         a
1  20230101     2         b
2  20230101     3         c
3  20230102     1         a
4  20230102     3         c
5  20230103     2         b
6  20230103     4         d

 

두 번째 방법도 droplevel()을 이용하나 좀 다른 방식으로 이용하는 것입니다.

 

 

MultiIndex([('number',      'date'),
            ('number',      'item'),
            ('string', 'item_name')],
           )

multi index를 출력해보면 위와 같습니다.

 

여기서 level=0 column은 number와 string입니다.

(이걸 보면 왜 위쪽에 명시된 컬럼이 level=0인지 알 수 있죠. tuple의 첫 번째 자리 즉, tuple의 index=0 자리에 명시되기 때문에 level=0 column이 되는 것입니다.)

 

df_test.columns.droplevel(level=0)

그리고 이런식으로 columns 속성에 있는 level=0 위치에 있는 level을 모두 drop하면

 

 

Index(['date', 'item', 'item_name'], dtype='object')

level=0 은 다 사라지고 level=1이었던 column name만 남게 됩니다.

 

 

 

- df_test.columns = df_test.columns.droplevel(level=0)

 

이렇게 level=1 column만 남은 column name 정보를 df_test.columns 속성에 덮어씌우는 것입니다.

 

이런식으로 기존 multi index DataFrame의 column 정보를 덮어씌워서 multi index를 제거하는 방법이 있습니다.

 

 

 

 

 

import pandas as pd

multi_cols = pd.MultiIndex.from_tuples(
    [
        ('number', 'date'),
        ('number', 'item'),
        ('string', 'item_name')
    ]
)

df_test = pd.DataFrame(
    [
        (20230101, 1, 'a'),
        (20230101, 2, 'b'),
        (20230101, 3, 'c'),

        (20230102, 1, 'a'),
        (20230102, 3, 'c'),

        (20230103, 2, 'b'),
        (20230103, 4, 'd'),
    ],
    columns=multi_cols
)

df_test.columns = ['date', 'item', 'item_name']

print(df_test)



-- Result
       date  item item_name
0  20230101     1         a
1  20230101     2         b
2  20230101     3         c
3  20230102     1         a
4  20230102     3         c
5  20230103     2         b
6  20230103     4         d

방금 전에 설명했던 방식과 비슷하게 multi index를 가지고 있는 DataFrame의 columns 속성에

내가 원하는 column 이름을 list의 형태로 전달하여 덮어 씌우는 것입니다.

 

 

 

 

 

 

MultiIndex([('number',      'date'),
            ('number',      'item'),
            ('string', 'item_name')],
           )

아까 위에서 multi index의 column은 위처럼 tuple로 묶인 형태로 표시된다는 것을 알면 이것을 이용하여 다양한 방법을 사용할 수 있습니다.

 

 

 

import pandas as pd

multi_cols = pd.MultiIndex.from_tuples(
    [
        ('number', 'date'),
        ('number', 'item'),
        ('string', 'item_name')
    ]
)

df_test = pd.DataFrame(
    [
        (20230101, 1, 'a'),
        (20230101, 2, 'b'),
        (20230101, 3, 'c'),

        (20230102, 1, 'a'),
        (20230102, 3, 'c'),

        (20230103, 2, 'b'),
        (20230103, 4, 'd'),
    ],
    columns=multi_cols
)

df_test.columns = [col[1] for col in df_test.columns]

print(df_test)



-- Result
       date  item item_name
0  20230101     1         a
1  20230101     2         b
2  20230101     3         c
3  20230102     1         a
4  20230102     3         c
5  20230103     2         b
6  20230103     4         d

 

이런 식으로 columns 속성을 참조하고

거기서 tuple 내에 index = 1위치에 있는 값으로만 list를 구성합니다.

그리고 df_test의 columns를 덮어씌우면 multi index가 제거되는 것이죠.

 

 

 

 

 

import pandas as pd

multi_cols = pd.MultiIndex.from_tuples(
    [
        ('number', 'date'),
        ('number', 'item'),
        ('string', 'item_name')
    ]
)

df_test = pd.DataFrame(
    [
        (20230101, 1, 'a'),
        (20230101, 2, 'b'),
        (20230101, 3, 'c'),

        (20230102, 1, 'a'),
        (20230102, 3, 'c'),

        (20230103, 2, 'b'),
        (20230103, 4, 'd'),
    ],
    columns=multi_cols
)

df_test.columns = ['_'.join(col) for col in df_test.columns]

print(df_test)



-- Result
   number_date  number_item string_item_name
0     20230101            1                a
1     20230101            2                b
2     20230101            3                c
3     20230102            1                a
4     20230102            3                c
5     20230103            2                b
6     20230103            4                d

이제 감이 오시나요.

위같은 방법도 존재합니다.

 

그래서 multi index는 DataFrame의 columns 속성 내에서

하나의 column에 대한 multi index가 tuple에 묶여서 존재한다는 사실만 안다면 이를 다양하게 이용할 수 있습니다.

 

 

 

 

 

 

728x90
반응형