[Pandas] MultiIndex
Pandas MultiIndex, 계층 인덱스, hierarchical index
정의
MultiIndex 는 여러 단계 (level) 의 라벨로 구성된 Pandas Index. SQL 의 composite key 와 비슷, 그룹화된 데이터를 자연스럽게 표현.
생성
# from_tuples
mi = pd.MultiIndex.from_tuples(
[('Seoul', 'A'), ('Seoul', 'B'), ('Busan', 'A')],
names=['city', 'dept']
)
# from_product (직교곱)
mi = pd.MultiIndex.from_product(
[['Seoul', 'Busan'], ['A', 'B']],
names=['city', 'dept']
)
# groupby 결과
df.groupby(['city', 'dept']).sum().index # 자동으로 MultiIndex
인덱싱
python
import pandas as pd
mi = pd.MultiIndex.from_tuples(
[('Seoul','A'),('Seoul','B'),('Busan','A'),('Busan','B')],
names=['city','dept']
)
df = pd.DataFrame({'sales':[100,200,150,250]}, index=mi)
print(df)
print('---')
print(df.loc['Seoul']) # outer level
print('---')
print(df.loc[('Seoul','A')]) # tuple 로 양쪽 level 결과
sales
city dept
Seoul A 100
B 200
Busan A 150
B 250
---
sales
dept
A 100
B 200
---
sales 100
Name: (Seoul, A), dtype: int64| city | dept | sales |
|---|---|---|
| Seoul | A | 100 |
| Seoul | B | 200 |
| Busan | A | 150 |
| Busan | B | 250 |
slice / cross-section
df.xs('Seoul', level='city') # cross-section
df.xs('A', level='dept')
# slice
df.loc[(slice(None), 'A'), :] # 모든 city 의 dept='A'
df.loc[pd.IndexSlice[:, 'A'], :] # 같음, 더 짧음
idx = pd.IndexSlice
df.loc[idx[:, 'A'], :]
stack / unstack 으로 변환
df.unstack('dept') # dept 가 컬럼 level 로
df.stack() # 컬럼 → index
level 조작
df.reset_index() # MultiIndex 해제 → 일반 컬럼
df.reset_index(level='dept') # 일부만 해제
df.swaplevel('city', 'dept') # level 순서 바꿈
df.sort_index(level=['city', 'dept']) # level 별 정렬
df.droplevel('dept') # level 제거
groupby 와의 자연스러운 결합
# groupby 결과는 자동 MultiIndex
result = df.groupby(['city', 'dept'])['sales'].sum()
result.unstack('dept') # 시각화에 좋은 wide format
MultiIndex 컬럼
행뿐 아니라 컬럼도 multi-level 가능.
df.pivot_table(index='city', columns=['dept', 'quarter'], values='sales')
# 컬럼이 (dept, quarter) MultiIndex
평탄화
df.columns = ['_'.join(map(str, c)) for c in df.columns]
# ('sales', 'A') → 'sales_A'
함정
1. tuple vs list
df.loc[('Seoul', 'A')] # 단일 인덱스
df.loc[[('Seoul', 'A')]] # 리스트 (DataFrame)
df.loc['Seoul', 'A'] # 행 라벨 + 컬럼 라벨로 해석 (다른 의미!)
2. SettingWithCopyWarning
MultiIndex 에서 더 자주 발생. 항상 .loc[idx, col] = 한 줄로.
3. sort 가 안 된 MultiIndex
df.loc['Seoul':'Busan'] # PerformanceWarning, lexsort 안 됨
df = df.sort_index() # 정렬 후 사용
참고
이 글의 용어 (3개)
- [Pandas] groupbypandas
- 정의 는 데이터를 그룹으로 나누고 (split), 각 그룹에 함수를 적용 (apply), 결과를 합쳐 (combine) 새 DataFrame 으로 만드는 split-apply-c…
- [Pandas] Indexpandas
- 정의 는 행 / 열 라벨을 보관하는 객체. / 의 모든 라벨은 Index. 정렬, 정합성, 빠른 lookup 의 기반. 기본은 RangeIndex (0, 1, 2, ...) 지만…
- [Pandas] stack / unstackpandas
- 정의 - : 가장 안쪽 컬럼 레벨 → 행 레벨 (DataFrame → Series 또는 더 좁은 DataFrame) - : 가장 안쪽 행 레벨 → 컬럼 레벨 / 의 MultiIn…
💬 댓글