본문 바로가기
판다스/중급 판다스

[pandas] 멀티 인덱스에서 특정 값 수정하기

by 김판다t 2023. 8. 23.

판다스 멀티 인덱스에서 특정 값 수정하기

이번 글에서는 판다스에서 멀티 인덱스 값을 일부 변경하는 다양한 방법을 다루겠습니다. 단계별로 예시를 통해 설명할 예정이니, 먼저 아래의 코드를 통해 예시 데이터프레임을 생성해 주세요.

import pandas as pd
data1 = {('A팀', '삼성전자'): [10, 20, 30, 30, 30], 
         ('A팀', '카카오'): [20, 20, 40, 40, 40], 
         ('B팀', '삼성전자'): [30, 30, 10, 10, 30], 
         ('B팀', '카카오'): [40, 40, 20, 20, 40], 
         ('C팀', '삼성전자'): [50, 50, 50, 50, 30], 
         ('C팀', '카카오'): [60, 60, 60, 60, 40]}

df = pd.DataFrame(data1)

 

df

 

단일 값 수정

 

하나의 값을 변경할 때는 rename 함수를 사용하는 것이 간결하고 효율적인 방법입니다. rename 함수는 멀티 인덱스에서도 동일하게 적용할 수 있어 간편하게 바꿀 수 있습니다. A팀을 1팀으로 바꾸고 싶다면 다음과 같은 코드를 사용합니다.

df1.rename({'A팀': '1팀'}, axis=1)

 

특정 레벨의 값 전체 수정하기

 

rename 함수는 개별적인 값을 수정하는 데 편리하지만, 멀티 인덱스의 특정 레벨 전체를 수정할 때는 다소 불편할 수 있습니다. 예를 들어, A팀, B팀, C팀을 각각 1팀, 2팀, 3팀으로 변경하는 경우, rename 함수로는 다음과 같이 작성할 수 있습니다.

# rename 함수로 첫 번째 레벨 모두 변경하기
df.rename({'A팀': '1팀', 'B팀': '2팀', 'C팀': '3팀'}, axis=1)

 

위 경우 첫 번째 레벨의 항목이 세 개뿐이라 rename 함수로도 가능하지만, 레벨의 항목이 많아질수록 번거로워질 것입니다. 

 

멀티 인덱스에서 특정 레벨의 값을 보다 간편하게 수정하려면 set_levels 함수를 사용하는 것이 더 효율적입니다. 이 함수는 인덱스 클래스에 적용되기에, df.columns에 적용한 후, 그 결과를 set_axis로 다시 데이터 프레임에 반영하는 방식입니다.

df.set_axis(df.columns.set_levels(['1팀', '2팀', '3팀'], level=0), axis=1)

 

 

또한 set_levels 함수를 사용하면 여러 레벨의 항목을 동시에 수정할 수 있습니다. 이번에는 첫 번째 레벨과 두 번째 레벨의 항목을 모두 수정해 보겠습니다. (위 결과에 추가로 삼성전자 → 삼전, 카카오 → KaKaO)

df.set_axis(df.columns.set_levels([['1팀', '2팀', '3팀'], ['삼전', 'KaKaO']]), axis=1)

 

set_levels 함수는 단일 혹은 복수의 레벨에서 레벨 전체를 바꿀 때 유용합니다.

 

멀티 인덱스의 구조를 변경하여 값 수정하기

 

rename과 set_levels는 모두 기존 멀티 인덱스의 구조를 변경하지 않습니다. 예를 들어, 데이터프레임 df의 첫 번째 레벨에는 A팀, B팀, C팀 세 가지 항목이 있고, 결과적으로 1팀, 2팀, 3팀의 세 가지 항목으로 변경될 뿐, 구조 자체는 그대로 유지됩니다.

 

그렇다면 구조를 변경해야 할 때는 어떻게 해야 할까요?

일단 현재 df의 컬럼즈의 구조부터 df.columns로 확인해 보겠습니다.

df1.columns
MultiIndex([('A팀', '삼성전자'),
            ('A팀',  '카카오'),
            ('B팀', '삼성전자'),
            ('B팀',  '카카오'),
            ('C팀', '삼성전자'),
            ('C팀',  '카카오')],
           )

 

첫 번째 레벨에는 A팀, B팀, C팀이라는 세 가지 항목이 있으며, 각각 A팀, A팀, B팀, B팀, C팀, C팀의 여섯 개 값을 가지고 있습니다. 이 여섯 개 값을 1팀, 2팀, 3팀, 4팀, 5팀, 6팀으로 변경하여 모두 각각 다른 값으로 할당해 보겠습니다. 항목의 개수가 달라지니 멀티 인덱스의 구조가 달라지기에 rename과 set_levels로는 수행할 수 없습니다.

 

이 경우 새로 할당할 값의 배열과 기존 두 번째 레벨의 배열을 튜플로 조합하여, pd.MultiIndex.from_tuples 메서드를 사용해 새로운 멀티 인덱스를 생성한 후 데이터프레임에 할당합니다. 기존 멀티 인덱스의 두 번째 레벨은 get_level_values로 가져올 수 있습니다. 

df.columns.get_level_values(1)
Index(['삼성전자', '카카오', '삼성전자', '카카오', '삼성전자', '카카오'], dtype='object')

 

기존 멀티 인덱스의 첫 번째 레벨은 교체될 예정이므로 새로 생성한 값을 변수 level0에 저장하고, get_level_values로 가져온 df.columns의 두 번째 레벨을 튜플로 조합해 pd.MultiIndex.from_tuples 메서드를 사용해 새로운 멀티 인덱스를 생성합니다.  새롭게 생성된 멀티 인덱스는 이전과 마찬가지로 set_axis 함수를 통해 df에 할당합니다.

# 새로 변경할 첫 번째 레벨 값들
level0 = ['1팀', '2팀', '3팀', '4팀', '5팀', '6팀']

# 새로운 첫 번째 레벨과 기존 두 번째 레벨을 조합하여 멀티 인덱스 생성
idx = pd.MultiIndex.from_tuples(zip(level0, df.columns.get_level_values(1)))

# 새롭게 생성한 멀티 인덱스를 데이터 프레임에 할당
df.set_axis(idx, axis=1)

 

※ 파이썬의 zip 함수 : 두 배열을 순서대로 짝지어 튜플로 묶는 함수

 

 

더욱 간결한 방법은 set_axis 함수에 새로운 첫 번째 레벨의 배열과 기존 두 번째 레벨의 배열을 리스트로 묶어 입력하는 것입니다.

# 새로 변경할 첫 번째 레벨 값들
level0 = ['1팀', '2팀', '3팀', '4팀', '5팀', '6팀']

# level0와 기존 두 번째 레벨의 배열을 리스트로 묶어 set_axis 함수에 입력
df.set_axis([level0, df.columns.get_level_values(1)], axis=1)

 

위 방법과 동일한 결과를 얻습니다.

 

결론

 

멀티 인덱스에서 값을 수정할 때는 단일 값을 수정할 때는 rename 함수를 사용하고, 레벨 전체를 변경할 때는 set_levels가 효과적입니다. 멀티 인덱스의 구조 자체를 변경해야 할 경우에는 새로운 멀티 인덱스를 생성하여 데이터프레임에 할당해야 합니다.


교보문고 구매 페이지, 알라딘 구매 페이지yes24 구매 페이지

 

 



유튜브에서 판다스 강의 중입니다.

https://www.youtube.com/@KimPandas