파이썬/데이터프레임 다루기

Pandas 데이터 포맷 전환: melt()와 pivot() 완전 정리

Data Jun 2025. 3. 24. 15:55

앞서 stack()과 unstack()으로 인덱스를 기준으로 데이터 구조를 전환하는 방법을 배웠습니다.
이번에는 melt()와 pivot()을 통해 컬럼을 기준으로 데이터 포맷을 자유롭게 변환해보겠습니다.

  • melt() → Wide → Long 형태로 변환
  • pivot() → Long → Wide 형태로 변환

이 두 함수는 데이터 시각화, 머신러닝 전처리, 분석 보고서 정리에 꼭 필요한 핵심 기능입니다.

 

예제 데이터 준비

import pandas as pd

df = pd.DataFrame({
    'student': ['혜선', '종훈', '지웅'],
    'math': [85, 90, 95],
    'english': [80, 88, 92]
})
print(df)

 

Wide 포맷 (원본)

  student  math  english
0     혜선    85       80
1     종훈    90       88
2     지웅    95       92

 

melt(): Wide → Long 변환

long_df = pd.melt(df, id_vars='student', var_name='subject', value_name='score')
print(long_df)

🔹 출력 결과

  student  subject  score
0     혜선     math     85
1     종훈     math     90
2     지웅     math     95
3     혜선  english     80
4     종훈  english     88
5     지웅  english     92

수학, 영어 점수가 열에서 행으로 녹여져(long) 하나의 열로 정리됨
시각화나 그룹 분석 시 매우 유용한 포맷

 

pivot(): Long → Wide 변환

wide_df = long_df.pivot(index='student', columns='subject', values='score')
print(wide_df)

🔹 출력 결과

subject  english  math
student                
혜선            80    85
종훈            88    90
지웅            92    95

다시 원래처럼 과목별 컬럼을 가진 Wide 포맷으로 되돌림
pivot()은 index, columns, values 세 축을 지정해야 함

 

 

melt()에서 id_vars를 다중 선택

df = pd.DataFrame({
    'name': ['혜선', '종훈'],
    'year': [2023, 2023],
    'math': [95, 88],
    'english': [89, 92]
})

melted = pd.melt(df, id_vars=['name', 'year'], var_name='subject', value_name='score')
print(melted)

✅ 출력

   name  year  subject  score
0   혜선  2023     math     95
1   종훈  2023     math     88
2   혜선  2023  english     89
3   종훈  2023  english     92

name과 year가 식별자 역할을 하고, 나머지 열이 녹아내림

 

melt()를 사용할 때 컬럼이 많거나, **과목 외의 다른 데이터(예: 성별, 학년 등)**가 함께 있는 경우, 어떻게 처리되는지 이해하는 게 정말 중요하죠.

 

핵심 개념 정리

  • id_vars는 "녹이지 말고 유지할 컬럼"
  • value_vars는 (옵션) "녹일 컬럼을 명시적으로 지정할 수 있음"
  • 아무 설정도 안 하면 id_vars 외의 모든 나머지 컬럼이 녹아내림

예제: 컬럼이 많은 경우

import pandas as pd

df = pd.DataFrame({
    'student': ['혜선', '종훈'],
    'gender': ['F', 'M'],
    'grade': [3, 2],
    'math': [90, 95],
    'english': [85, 92],
    'science': [88, 90]
})

이 상태에서 pd.melt(df, id_vars=['student'])를 실행하면?

melted = pd.melt(df, id_vars=['student'])
print(melted)

출력 결과:

  student variable value
0     혜선   gender     F
1     종훈   gender     M
2     혜선    grade     3
3     종훈    grade     2
4     혜선     math    90
5     종훈     math    95
6     혜선  english    85
7     종훈  english    92
8     혜선  science    88
9     종훈  science    90

 

그런데 우리는 점수 컬럼만 녹이고, gender와 grade는 유지하고 싶다면?

pd.melt(df,
        id_vars=['student', 'gender', 'grade'],
        value_vars=['math', 'english', 'science'],
        var_name='subject',
        value_name='score')

출력 결과:

  student gender  grade  subject  score
0     혜선      F      3     math     90
1     종훈      M      2     math     95
2     혜선      F      3  english     85
3     종훈      M      2  english     92
4     혜선      F      3  science     88
5     종훈      M      2  science     90

 

요약 정리

 

 

pivot() vs pivot_table() 차이점은?

예시 비교

df = pd.DataFrame({
    'student': ['혜선', '혜선', '종훈'],
    'subject': ['math', 'math', 'math'],
    'score': [95, 100, 90]
})

# pivot() ❌
# df.pivot(index='student', columns='subject', values='score') → ValueError

# pivot_table() ✅
pivoted = df.pivot_table(index='student', columns='subject', values='score', aggfunc='mean')
print(pivoted)

 

pivot()은 index + columns 조합이 유일해야 정상적으로 작동합니다

 

→ ValueError: Index contains duplicate entries, cannot reshape
동일한 index+column 조합이 중복되면 pivot()은 실패합니다.

✔️ 해결 방법

중복이 있을 가능성이 있다면 pivot_table()을 사용하세요.
자동으로 평균, 합계 등 원하는 방식으로 집계(aggregation) 해줍니다.

 

정리

 

실무 활용 팁

  • melt()는 시각화 전 구조 변경에 필수
  • pivot()은 데이터 요약 결과를 보기 좋게 재정렬할 때 유용
  • 둘 다 Pandas에서 가장 자주 쓰이는 포맷 변환 도구 중 하나
  • melt()는 원본 데이터를 Long format으로 정리할 때 유용
  • 시각화나 그룹 통계 시, 분석 대상 컬럼만 녹이는 것이 일반적
  • 컬럼 수가 많을수록 id_vars / value_vars는 꼭 명시하는 습관 들이기