판다스 멀티 인덱스에서 특정 값 수정하기
이번 글에서는 판다스에서 멀티 인덱스 값을 일부 변경하는 다양한 방법을 다루겠습니다. 단계별로 예시를 통해 설명할 예정이니, 먼저 아래의 코드를 통해 예시 데이터프레임을 생성해 주세요.
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
'판다스 > 중급 판다스' 카테고리의 다른 글
[pandas] 특정 열의 값을 기준으로 행을 선택하는 방법 (0) | 2024.05.22 |
---|---|
[pandas] 영업일(business day)을 배열로 생성하는 방법 (0) | 2023.08.28 |
[pandas] 범주형 데이터를 정수로 코드화하는 다양한 방법 (0) | 2023.05.27 |
[pandas] 시리즈에 apply 대신 map 함수로 매핑하는 이유 (0) | 2023.05.27 |
[pandas] 숫자로 바꿀 때 to_numeric과 astype의 차이 (0) | 2022.06.13 |