7 / 8

파이썬 pandas 데이터 분석 입문 · 7장

merge·concat·melt로 데이터 합치고 모양 바꾸기

merge의 how 옵션(inner·left·outer), concat, pivot과 melt로 넓은 표·긴 표 바꾸기

3분 읽기

데이터는 한 표에 다 모여 있지 않은 경우가 많습니다. 이 장에서는 표를 옆으로 붙이는 merge, 아래로 이어 붙이는 concat, 표의 모양을 바꾸는 pivot과 melt를 실습합니다.

merge — 공통 열로 옆에 붙이기

메뉴의 분류(커피/디저트)는 다른 표에 있다고 해 봅시다.

Pythonmenu_info = pd.DataFrame({
    'menu': ['아메리카노', '라떼', '케이크'],
    'category': ['커피', '커피', '디저트'],
})

merged = sales.merge(menu_info, on='menu', how='left')
merged[['date', 'store', 'menu', 'category', 'revenue']].head(4)
결과         date store        menu category  revenue
0  2026-03-01  강남  아메리카노     커피   135000
1  2026-03-01  홍대        라떼     커피    60000
2  2026-03-02  강남        라떼     커피    90000
3  2026-03-02  홍대  아메리카노     커피   112500

이제 분류별 집계도 할 수 있습니다.

Pythonmerged.groupby('category')['revenue'].sum()
결과category
디저트    104000
커피      598500
Name: revenue, dtype: int64

how — 어느 쪽 행을 남길까

how남는 행SQL로 치면
'inner' (기본값)양쪽에 모두 있는 키INNER JOIN
'left'왼쪽 표의 모든 행LEFT JOIN
'right'오른쪽 표의 모든 행RIGHT JOIN
'outer'양쪽 모든 행FULL OUTER JOIN

concat — 같은 모양의 표를 아래로 이어 붙이기

4월 데이터가 새로 들어왔다면 concat으로 이어 붙입니다.

Pythonapril = pd.DataFrame({'date': ['2026-04-01'], 'store': ['강남'],
                      'menu': ['라떼'], 'qty': [20], 'price': [5000]})

both = pd.concat([sales.drop(columns='revenue'), april], ignore_index=True)
both.tail(2)
결과         date store  menu  qty  price
7  2026-03-04  홍대  라떼   15   5000
8  2026-04-01  강남  라떼   20   5000

ignore_index=True를 주면 인덱스를 0부터 다시 매깁니다.

pivot과 melt — 넓은 표와 긴 표

같은 데이터도 두 가지 모양으로 담을 수 있습니다. 날짜별 매장 판매량을 넓은 표로 만들면 사람이 읽기 좋습니다.

Pythonwide = sales.pivot_table(index='date', columns='store', values='qty', aggfunc='sum')
wide
결과store       강남  홍대
date
2026-03-01    30    12
2026-03-02    18    25
2026-03-03    28     7
2026-03-04     9    15

반대로 melt는 넓은 표를 한 행에 한 관측값이 있는 긴 표로 되돌립니다. 그래프 라이브러리와 groupby는 긴 표를 더 잘 다룹니다.

Pythonlong = wide.reset_index().melt(id_vars='date', var_name='store', value_name='qty')
long.head(4)
결과         date store  qty
0  2026-03-01  강남   30
1  2026-03-02  강남   18
2  2026-03-03  강남   28
3  2026-03-04  강남    9

전체 메뉴