Skip to content

Pandas MultiIndex: 계층 인덱싱 완전 정복 가이드

Updated on

MultiIndex는 panel 데이터, 시계열, 피벗·리셰이프된 데이터에 대해 깔끔한 계층 구조를 제공하지만, 슬라이싱이 불안정하게 느껴지고 level 순서가 헷갈린다는 이유로 많은 사용자가 사용을 꺼립니다.

  • 문제: (region + year, symbol + field 같은) 중첩 차원을 일반 컬럼이나 wide 테이블에 그대로 두면 점점 지저분해집니다.
  • 긴장: 임시방편으로 reshape를 반복하다 보면 중복된 컬럼명, 정렬 깨짐, 다중 키 선택 시 에러가 자주 발생합니다.
  • 해결: 소수의 반복 가능한 패턴을 사용하세요. set_index로 MultiIndex를 만들고, .loc/.xs로 안전하게 슬라이스하며, swaplevel/reorder_levels로 level을 재배열하고, stack/unstack으로 형태를 변환합니다.

Want an AI agent that understands your pandas notebooks and MultiIndex slicing?

RunCell is a JupyterLab AI agent that can read your code, analyze DataFrames, understand notebook context, debug errors, and even generate & execute code for you. It works directly inside JupyterLab—no switching windows or copy-pasting.

👉 Try RunCell: runcell.dev (opens in a new tab)


빠른 참고(Quick Reference)

작업메서드코드 스니펫
컬럼에서 계층 인덱스 생성set_indexdf.set_index(["region", "year"]).sort_index()
Cartesian product로 생성pd.MultiIndex.from_productpd.MultiIndex.from_product([regions, years], names=["region", "year"])
특정 level 기준 슬라이스.loc 또는 .xsdf.loc[("EMEA", 2024)] 또는 df.xs("EMEA", level="region")
level 순서 재배치swaplevel, reorder_levelsdf.swaplevel("region", "year")
level 삭제 또는 평탄화droplevel, reset_indexdf.droplevel("year"), df.reset_index()
wide/long 변환unstack / stackdf.unstack("field"), df.stack("field")

예제 데이터

import pandas as pd
 
records = [
    ("EMEA", 2023, "revenue", 120),
    ("EMEA", 2023, "profit", 25),
    ("EMEA", 2024, "revenue", 140),
    ("NA", 2024, "revenue", 210),
    ("NA", 2024, "profit", 50),
]
 
df = (
    pd.DataFrame(records, columns=["region", "year", "metric", "value"])
      .set_index(["region", "year", "metric"])
      .sort_index()
)

MultiIndex 구조 만들기

기존 컬럼에서 생성하기

sales = raw_df.set_index(["region", "year"]).sort_index()
  • 여러 level을 걸친 슬라이싱을 예측 가능하게 하려면 sort_index()를 사용하세요.
  • 금액처럼 일반 컬럼으로 남겨두고 싶은 값은 index로 보내지 않고 컬럼에 유지하세요.

product 또는 튜플에서 생성하기

idx = pd.MultiIndex.from_product(
    [["EMEA", "NA"], [2023, 2024]],
    names=["region", "year"],
)
frame = pd.DataFrame(index=idx, columns=["revenue"]).sort_index()

from_product는 모든 조합이 존재하도록 보장합니다. 이미 (region, year) 쌍이 리스트로 준비돼 있다면 from_tuples를 사용하세요.


MultiIndex로 선택하기

# 계층을 따라 한 경로를 지정
emea_2024 = df.loc[("EMEA", 2024)]
 
# 특정 level에 대한 단면(cross section), 나머지 level은 유지
emea = df.xs("EMEA", level="region")
 
# 슬라이스를 이용한 부분 선택 (정렬된 인덱스 필요)
idx = pd.IndexSlice
subset = df.loc[idx[:, 2024, :], :]
  • .xs(cross-section)는 나머지 level 구조를 유지한 채 특정 level만 잘라낼 때 유용합니다.
  • 시계열 계층에서는 index를 정렬한 뒤 IndexSlice로 범위를 지정하면 가독성이 좋아집니다.

level 재배치 및 정리

# year를 region 앞에 가져오기
reordered = df.swaplevel("region", "year").sort_index(level=["year", "region"])
 
# 3개 이상의 level을 명시적으로 재배열
df_reordered = df.reorder_levels(["metric", "region", "year"])
 
# 더 이상 필요 없는 level은 제거
flat = df.droplevel("metric")
  • swaplevel은 인접한 두 level을 빠르게 교환할 때, reorder_levels는 임의의 순서로 재배열할 때 사용합니다.
  • 재배열 후에는 sort_index(level=...)를 호출해 부분 슬라이싱에 필요한 단조(monotonic) 정렬을 복원하세요.

Stack / Unstack으로 리셰이프하기

index level을 축으로 삼아 wide ↔ long 형태를 자유롭게 변환할 수 있습니다.

wide = df.unstack("metric")  # metric 값이 컬럼으로 이동
long_again = wide.stack("metric")
  • 존재하지 않는 조합에 값을 채우려면 unstack에서 fill_value=를 사용하세요.
  • 컬럼 기준으로 pivot 스타일 변환을 할 때는 수동 루프 대신 set_index([...]).unstack()stack() 조합을 활용하는 것이 좋습니다.

MultiIndex vs 일반 컬럼, 언제 무엇을 쓸까?

상황MultiIndex 사용일반 컬럼 사용
계층적 라벨이 슬라이싱의 중심 (region → year → metric).loc/.xs로 자연스럽게 처리⚠️ 반복 필터링/조인이 필요
보고용 wide 레이아웃✅ 필요할 때 unstack으로 컬럼화⚠️ 컬럼명 중복 위험
키 컬럼으로 자주 merge⚠️ 먼저 reset 후 merge✅ 키를 컬럼으로 둔 채 join
CSV/Parquet로 내보내기✅ 쓰기 전에 reset_index()✅ 별도 단계 불필요

실무 기준: 외부 시스템과 주고받는 저장 형태에서는 키를 명확한 컬럼으로 유지하고, 내부 분석 워크플로에서 계층 슬라이싱·리셰이프가 핵심이면 MultiIndex를 적극 활용하는 것이 좋습니다.


자주 발생하는 함정과 해결책

  • 정렬되지 않은 인덱스로 인한 슬라이싱 실패: 부분 슬라이스 전에 sort_index(level=[...])를 호출하세요.
  • 이름 없는 level: 슬라이싱과 reset_index 동작을 명확히 하려면 index.names(또는 set_indexnames=)를 설정하세요.
  • 읽기 어려운 출력: df.index.to_frame()으로 각 level을 컬럼처럼 확인할 수 있고, 필요할 때 reset_index()로 평탄한 컬럼 구조로 되돌릴 수 있습니다.

MultiIndex를 만드는, 슬라이스하는, 재정렬하는, 리셰이프하는 방식을 패턴으로 표준화하면, 계층 구조의 장점을 혼란 없이 누릴 수 있습니다. 이 패턴들을 pandas-pivot-melt 같은 reshaping 가이드, pandas-resample 같은 시계열 도우미와 함께 사용하면, 다차원 데이터를 처음부터 끝까지 일관되게 관리할 수 있습니다.