0Pricing
Pandas & NumPy Academy · 강의

MultiIndex에서 stack과 unstack 사용하기

stack()으로 가장 안쪽의 열 수준을 행 인덱스로 옮기고 unstack()으로 되돌립니다.

MultiIndex에서 stack과 unstack 사용하기은(는) CoddyKit의 무료 Pandas & NumPy Academy 강의입니다. 이것은 4개 중 3번째 강의입니다. 아래에서 전체 강의를 무료로 읽을 수 있으며, 내장 코드 에디터와 24/7 AI 튜터와 함께 브라우저에서 직접 실습할 수 있습니다. 이 강의는 Pandas & NumPy Academy 학습 경로의 일부이며, 진행 상황이 웹과 CoddyKit 앱에 동기화됩니다. Pandas & NumPy Academy 강의에는 총 4개의 강의가 포함되어 있습니다.

stack과 unstack 소개

stack()과 unstack()은 데이터를 행 인덱스와 열 인덱스 사이에서 이동시키는 Pandas 형태 변환 도구입니다. 두 축 중 하나에 MultiIndex가 있는 DataFrames를 다룰 때 특히 유용합니다. stack()은 가장 안쪽 열 수준을 가장 안쪽 행 수준으로 회전시키고, unstack()은 그 반대 작업을 수행합니다.

stack(): 열을 행으로

DataFrame.stack()은 열 레이블의 가장 안쪽 수준을 행 인덱스의 가장 안쪽 수준으로 피벗하여, 더 길고 더 좁은 결과를 만듭니다. 원래 DataFrame의 열이 단순한 열(다중 열이 아님)이었다면 결과는 MultiIndex가 있는 Series가 됩니다. 열에 여러 수준이 있었다면 stack()은 열 수준을 하나 줄입니다.

import pandas as pd

df = pd.DataFrame({
    'Math': [85, 90, 78],
    'Science': [92, 88, 95]
}, index=['Alice', 'Bob', 'Carol'])

print(df)
#        Math  Science
# Alice    85       92
# Bob      90       88
# Carol    78       95

stacked = df.stack()
print(stacked)
# Alice    Math       85
#          Science    92
# Bob      Math       90
#          Science    88
# Carol    Math       78
#          Science    95
# dtype: int64

unstack(): 행을 열로

Series.unstack()(또는 DataFrame.unstack())은 stack()의 역연산입니다. 행 인덱스의 가장 안쪽 수준을 가져와 새 열 레이블로 회전시키므로 더 넓은 결과가 만들어집니다. 기능적으로는 pivot()과 비슷하지만, 열의 값이 아니라 인덱스에 직접 적용됩니다.

stacked = df.stack()
print(type(stacked))  # Series with MultiIndex

# Restore the original wide format
df_restored = stacked.unstack()
print(df_restored)
#        Math  Science
# Alice    85       92
# Bob      90       88
# Carol    78       95

# Identical to the original df!

stack할 수준 선택하기

열에 MultiIndex가 있는 DataFrames에서는 stack(level)을 사용하여 회전할 수준을 선택할 수 있습니다. 수준 번호(가장 바깥쪽은 0, 가장 안쪽은 -1이며 기본값) 또는 수준 이름을 전달하십시오. 마찬가지로 unstack(level)은 열로 회전할 행 인덱스 수준을 선택합니다. 이러한 세밀한 제어는 복잡한 계층적 데이터 구조를 탐색하는 데 필수적입니다.

# MultiIndex columns
arrays = [['Math', 'Math', 'Science', 'Science'],
          ['Q1', 'Q2', 'Q1', 'Q2']]
multi_cols = pd.MultiIndex.from_arrays(arrays, names=['subject', 'quarter'])

df_multi = pd.DataFrame([[85, 90, 92, 88], [78, 80, 95, 91]],
                        index=['Alice', 'Bob'], columns=multi_cols)

# Stack the 'quarter' level (innermost, level=-1)
print(df_multi.stack(level='quarter').head())

특정 행 수준에 unstack() 적용하기

DataFrame의 행에 MultiIndex가 있는 경우(여러 열에 대해 groupby()를 적용한 후 흔히 발생합니다), 특정 행 수준에 unstack()을 적용하여 해당 수준을 열 전체로 펼칠 수 있습니다. 이는 pivot_table()을 명시적으로 호출하지 않고 교차표 형태의 요약을 만들 때 매우 흔히 사용하는 패턴입니다.

# GroupBy produces MultiIndex rows
df2 = pd.DataFrame({
    'region': ['East', 'East', 'West', 'West'],
    'product': ['A', 'B', 'A', 'B'],
    'sales': [100, 150, 120, 200]
})

# MultiIndex result from groupby
multi = df2.groupby(['region', 'product'])['sales'].sum()
print(multi)

# Unstack the product level into columns
wide = multi.unstack('product')
print(wide)
# product    A    B
# region
# East     100  150
# West     120  200

stack/unstack에서 결측값 처리하기

unstack()을 호출했을 때 모든 열 수준에 대해 모든 행 인덱스 조합이 존재하지 않으면 Pandas는 누락된 셀을 NaN으로 채웁니다. 반대로 stack()은 기본적으로 값이 모두 NaN인 행을 제거합니다. dropna 매개변수로 이 동작을 제어할 수 있습니다. stack(dropna=False)를 전달하면 NaN 행을 유지할 수 있습니다.

# Incomplete data: West has no product B
df3 = df2[df2['product'] != 'B'].copy()
multi3 = df3.groupby(['region', 'product'])['sales'].sum()

wide3 = multi3.unstack('product', fill_value=0)
print(wide3)
# product    A    B
# region
# East     100    0  <- B filled with 0 instead of NaN
# West     120    0

stack() 후 행에 계산 적용하기

강력한 패턴 중 하나는 넓은 DataFrame에 stack()을 적용하여 열을 행으로 변환하고, 필터링이나 groupby 같은 행 단위 작업을 적용한 다음, unstack()을 적용하여 다시 넓은 형식으로 되돌리는 것입니다. 이렇게 하면 열마다 반복문을 작성할 필요가 없고 코드가 벡터화되어 읽기 쉬워집니다. 모든 열에 동일한 변환을 동시에 적용할 때 특히 유용합니다.

# Normalise each column by its column mean using stack/compute/unstack
normalised = (
    df.stack()
      .groupby(level=1)
      .transform(lambda s: (s - s.mean()) / s.std())
      .unstack()
)
print(normalised.round(2))
#        Math  Science
# Alice  0.0     0.39
# Bob    1.13   -1.09
# Carol -1.13    0.71

플로팅을 위한 stack()

melt()와 마찬가지로 stack()은 데이터를 긴 형식으로 변환하며, 이는 Seaborn과 많은 Matplotlib 도우미 함수가 요구하는 형식입니다. 주요 차이점은 stack()이 열 인덱스에 작동하고 MultiIndex 구조를 유지하는 반면, melt()는 평평한 긴 형식 DataFrame을 만든다는 것입니다. 두 방법 모두 비슷한 플로팅 작업 흐름으로 이어집니다.

# Prepare data for line plot using stack
long = df.stack().reset_index()
long.columns = ['student', 'subject', 'score']
print(long)
#   student  subject  score
# 0   Alice     Math     85
# 1   Alice  Science     92
# ...

# Ready for: sns.barplot(data=long, x='student', y='score', hue='subject')

인덱스 순서 변경을 위한 swaplevel()

stack한 후에는 가장 안쪽 행 수준이 원래 열 이름이 됩니다. 때로는 바깥쪽 수준을 변수 이름으로, 안쪽 수준을 원래 행 인덱스로 만들고 싶을 수 있습니다. MultiIndex에 swaplevel()을 사용하여 두 수준의 순서를 바꾼 다음, sort_index()로 깔끔한 정렬 순서를 복원하십시오.

stacked = df.stack()  # MultiIndex: (student, subject)
swapped = stacked.swaplevel()  # MultiIndex: (subject, student)
swapped = swapped.sort_index()
print(swapped)
# subject  student
# Math     Alice      85
#          Bob        90
#          Carol      78
# Science  Alice      92
#          Bob        88
#          Carol      95

stack, melt, pivot 중 무엇을 사용할까

MultiIndex 열 DataFrames를 다루면서 열 수준을 하나 줄이고 싶다면 stack()을 선택하십시오. 평평한 DataFrame을 가지고 있고 어떤 열을 행으로 바꿀지 제어하면서 넓은 형식에서 긴 형식으로 변환하려면 melt()를 선택하십시오. 긴 형식에서 다시 넓은 형식으로 변환하려면 pivot()/pivot_table()을 선택하십시오. 이 세 도구로 Pandas에서 필요한 모든 넓은 형식/긴 형식 변환을 처리할 수 있습니다.

# Decision guide (comment, not executable standalone):
# MultiIndex columns -> want fewer levels: use stack()
# Flat wide -> need long format for plotting/ML: use melt()
# Long -> need wide summary table: use pivot_table()
# Wide -> back to long: use melt() or stack()

# Example: stack when you have pivot_table output (MultiIndex cols)
tbl = df2.groupby(['region', 'product'])['sales'].sum().unstack()
long_again = tbl.stack().rename('sales').reset_index()
print(long_again)

실전 요약: 형태 변환 요령표

다음과 같이 간단히 기억하면 됩니다. stack() — 열이 행으로 합쳐져 DataFrame이 더 좁고 길어집니다. unstack() — 행이 열로 펼쳐져 DataFrame이 더 넓고 짧아집니다. melt() — 이름이 있는 열이 키-값 쌍(새 열 두 개)으로 합쳐집니다. pivot_table() — 키-값 열이 여러 열로 펼쳐집니다. 네 가지 방법은 모두 서로 되돌릴 수 있으며, 어느 방향으로 변환할지는 대상 분석에서 넓은 형식과 긴 형식 중 어느 쪽을 선호하는지에 따라 결정하면 됩니다.

# stack/unstack cycle
df_wide = df.copy()             # wide format
df_long = df_wide.stack()       # long via stack
df_wide2 = df_long.unstack()    # back to wide

# melt/pivot cycle
df_melted = df_wide.melt(id_vars=[])    # wide -> long
# df_pivoted = df_melted.pivot(...)     # long -> wide

print('Original shape:  ', df_wide.shape)
print('After stack:     ', df_long.shape)
print('After unstack:   ', df_wide2.shape)

빠른 확인

이 수업에서 배운 MultiIndex와 stack 및 unstack에 대한 이해도를 확인해 보십시오.

수업 요약

이 수업에서는 다음을 배웠습니다. stack()은 열 레이블을 행 인덱스로 회전시켜 더 길고 좁은 결과를 만듭니다. unstack()은 그 반대로 행 인덱스 수준을 열로 회전시킵니다. 두 방법 모두 groupby 작업으로 만들어진 MultiIndex 구조에서 작동하며, swaplevel()을 사용하면 인덱스 수준의 순서를 바꿀 수 있습니다. 다음으로는 범주형 열 사이의 빈도표를 빠르게 만드는 pd.crosstab()을 살펴보겠습니다.

자주 묻는 질문

“MultiIndex에서 stack과 unstack 사용하기” 강의는 무료인가요?

네 — “MultiIndex에서 stack과 unstack 사용하기” 전체 내용을 이 웹사이트에서 무료로 읽을 수 있습니다. 인터랙티브하게 실습하려면(내장 코드 에디터와 24/7 AI 튜터), CoddyKit PRO로 업그레이드하면 Pandas & NumPy Academy 강의 전체를 잠금 해제할 수 있습니다. Pandas & NumPy Academy 강의에는 총 4개의 강의가 포함되어 있습니다.

“MultiIndex에서 stack과 unstack 사용하기”에서 뭘 배우나요?

stack()으로 가장 안쪽의 열 수준을 행 인덱스로 옮기고 unstack()으로 되돌립니다. 브라우저에서 직접 실행하는 실습 코드로 Pandas & NumPy Academy을(를) 배우며, 24/7 AI 튜터가 강의를 진행하면서 질문에 답변해줍니다.

Pandas & NumPy Academy을(를) 시작하는 데 경험이 필요한가요?

사전 경험은 필요하지 않습니다. CoddyKit의 Pandas & NumPy Academy은(는) 초급자부터 고급 학습자까지를 위해 구성되어 있으므로, 여기서 시작하거나 처음부터 시작할 수 있으며 자신의 속도대로 진행할 수 있습니다. 이것은 4개 중 3번째 강의입니다.

“MultiIndex에서 stack과 unstack 사용하기” 강의는 얼마나 걸리나요?

대부분의 CoddyKit 강의는 약 5~10분이 소요됩니다. 각 강의는 간결하고 인터랙티브하여 꾸준한 진행이 가능하며, 웹과 앱에서 중단한 부분부터 바로 시작할 수 있습니다.

이 Pandas & NumPy Academy 강의에서 코드를 작성하고 실행할 수 있나요?

네. 모든 Pandas & NumPy Academy 강의에는 내장 코드 에디터가 포함되어 있으므로, 브라우저에서 바로 실제 코드를 작성하고 실행한 후 즉시 AI 피드백을 받을 수 있습니다 — 로컬 설정이 필요 없습니다.

이 강의의 모든 강의

  1. pivot_table: 교차 집계
  2. melt: 넓은 형식에서 긴 형식으로
  3. MultiIndex에서 stack과 unstack 사용하기
  4. 빈도표에 crosstab 사용하기
← Pandas & NumPy Academy(으)로 돌아가기