본문 바로가기
Data Science

Pandas | merge()와 join()

by Sseul.dev 2025. 10. 18.

"두 개의 DataFrame을 합치고 싶다면?"

엑셀의 VLOOKUP처럼 Pandas에서도 데이터를 합칠 수 있습니다! 


목차

1. 왜 필요할까?

2. merge() vs join() 핵심 차이

3. merge()

4. join() 

5. 조인 타입 4가지

6. 실전 팁


1. 왜 필요할까?

실생활 예시

온라인 쇼핑몰 데이터:

[회원 정보]              [주문 정보]
회원ID | 이름            주문ID | 회원ID | 상품
1001  | 김민수          O001  | 1001  | 노트북
1002  | 이영희          O002  | 1002  | 마우스
1003  | 박철수          O003  | 1001  | 키보드

"김민수가 뭘 샀는지 알고 싶다면?" → 회원ID를 기준으로 두 테이블을 합쳐야 합니다!


2. merge() vs join() 핵심 차이

구분 merge() join()
기본 기준 컬럼 인덱스
사용법 pd.merge(df1, df2) df1.join(df2)
간결성 보통 짧음
유연성 높음 보통
언제? 대부분의 경우 ✅ 인덱스 조인만

결론: 처음엔 merge()만 써도 충분합니다!


3. merge() 완전 정복

1) 기본: 컬럼으로 합치기

import pandas as pd

# 회원 정보
members = pd.DataFrame({
    'user_id': [101, 102, 103],
    'name': ['김민지', '이하늘', '박서준']
})

# 주문 정보
orders = pd.DataFrame({
    'user_id': [101, 102, 101],
    'product': ['노트북', '마우스', '키보드']
})

# user_id 기준으로 합치기
result = pd.merge(members, orders, on='user_id')
print(result)

 

출력:

   user_id  name product
0      101  김민지   노트북
1      101  김민지   키보드
2      102  이하늘   마우스

 

그림으로 이해하기:

members                orders
┌───────┬──────┐        ┌───────┬────────┐
│user_id│ name │        │user_id│ product│
├───────┼──────┤        ├───────┼────────┤
│  101  │ 김민지 │   →    │  101  │  노트북 │
│  102  │ 이하늘 │   +    │  102  │  마우스 │
│  103  │ 박서준 │        │  101  │  키보드 │
└───────┴──────┘        └───────┴────────┘
                              ↓
                    merge(on='user_id')
                              ↓
            ┌───────┬──────┬───────┐
            │user_id│ name │product│
            ├───────┼──────┼───────┤
            │  101  │ 김민지 │ 노트북 │
            │  101  │ 김민지 │ 키보드 │
            │  102  │ 이하늘 │ 마우스 │
            └───────┴──────┴───────┘
            (박서준은 주문이 없어서 제외)

2) 컬럼명이 다를 때

students = pd.DataFrame({
    'student_id': [201, 202, 203],
    'name': ['철수', '영희', '민수']
})

grades = pd.DataFrame({
    'id': [201, 202, 203],  # 컬럼명이 다름!
    'score': [85, 92, 78]
})

# left_on, right_on 사용
result = pd.merge(students, grades, 
                  left_on='student_id', right_on='id')
print(result)

 

출력:

   student_id  name  id    score
0       201     철수  201     85
1       202     영희  202     92
2       203     민수  203     78

3) 인덱스로 합치기

# 인덱스가 있는 데이터
employees = pd.DataFrame({
    'name': ['김대리', '이과장', '박부장'],
    'dept': ['개발', '기획', '영업']
}, index=[1001, 1002, 1003])

salaries = pd.DataFrame({
    'salary': [5000, 6000, 7000]
}, index=[1001, 1002, 1003])

# 인덱스 기준 합치기
result = pd.merge(employees, salaries, 
                  left_index=True, right_index=True)
print(result)

 

출력:

      name   dept  salary
1001  김대리   개발    5000
1002  이과장   기획    6000
1003  박부장   영업    7000

 

그림으로 이해:

employees (인덱스=사번)     salaries (인덱스=사번)
┌────┬────┬────┐         ┌────┬──────┐
│    │name│dept│         │    │salary│
├────┼────┼────┤         ├────┼──────┤
│1001│김대리│ 개발│    +    │1001│ 5000 │
│1002│이과장│ 기획│         │1002│ 6000 │
│1003│박부장│ 영업│         │1003│ 7000 │
└────┴────┴────┘         └────┴──────┘
           ↓
merge(left_index=True, right_index=True)
           ↓
    ┌────┬────┬────┬──────┐
    │    │name│dept│salary│
    ├────┼────┼────┼──────┤
    │1001│김대리│개발 │ 5000 │
    │1002│이과장│기획 │ 6000 │
    │1003│박부장│영업 │ 7000 │
    └────┴────┴────┴──────┘

 


4. join() 

1) 기본: 인덱스로 합치기

# 상품 정보 (인덱스 = 상품코드)
products = pd.DataFrame({
    'name': ['노트북', '마우스', '키보드'],
    'brand': ['삼성', 'LG', '로지텍']
}, index=['P001', 'P002', 'P003'])

# 재고 정보 (인덱스 = 상품코드)
stocks = pd.DataFrame({
    'qty': [10, 50, 30],
    'location': ['서울', '부산', '대구']
}, index=['P001', 'P002', 'P003'])

# 간단하게 합치기!
result = products.join(stocks)
print(result)

 

출력:

      name  brand  qty  location
P001  노트북   삼성   10     서울
P002  마우스   LG    50     부산
P003  키보드  로지텍   30     대구

💡 포인트: 인덱스 조인은 join()이 훨씬 간단!


2) 컬럼으로 합치기

# 왼쪽: 컬럼에 ID
authors = pd.DataFrame({
    'author_id': [401, 402, 403],
    'name': ['김작가', '이작가', '박작가']
})

# 오른쪽: 인덱스에 ID
books = pd.DataFrame({
    'title': ['소설', '시집', '에세이']
}, index=[401, 402, 403])

# on 옵션 사용
result = authors.join(books, on='author_id')
print(result)

 

출력:

   author_id   name   title
0      401     김작가    소설
1      402     이작가    시집
2      403     박작가    에세이

3) 컬럼명 충돌 시

df1 = pd.DataFrame({
    'name': ['강남점', '홍대점']
}, index=[1, 2])

df2 = pd.DataFrame({
    'name': ['A지점', 'B지점']  # 같은 'name' 컬럼!
}, index=[1, 2])

# lsuffix, rsuffix로 구분
result = df1.join(df2, lsuffix='_left', rsuffix='_right')
print(result)

 

출력:

   name_left name_right
1      강남점       A지점
2      홍대점       B지점

 


5. 조인 타입 4가지

모든 조인에서 how 옵션으로 선택 가능!

시각적 이해

# 데이터 준비
df_left = pd.DataFrame({
    'key': ['A', 'B', 'C'],
    'value': [1, 2, 3]
})

df_right = pd.DataFrame({
    'key': ['B', 'C', 'D'],
    'score': [10, 20, 30]
})

 

그림으로 보는 조인 타입:

df_left          df_right
┌───┬─────┐     ┌───┬─────┐
│key│value│     │key│score│
├───┼─────┤     ├───┼─────┤
│ A │  1  │     │ B │ 10  │
│ B │  2  │     │ C │ 20  │
│ C │  3  │     │ D │ 30  │
└───┴─────┘     └───┴─────┘

═══════════════════════════════════

1️⃣ INNER (교집합)
   how='inner' (기본값)
   
   ┌───┬─────┬─────┐
   │key│value│score│
   ├───┼─────┼─────┤
   │ B │  2  │ 10  │ ✅ 양쪽 모두 존재
   │ C │  3  │ 20  │ ✅ 양쪽 모두 존재
   └───┴─────┴─────┘

═══════════════════════════════════

2️⃣ LEFT (왼쪽 전체)
   how='left'
   
   ┌───┬─────┬─────┐
   │key│value│score│
   ├───┼─────┼─────┤
   │ A │  1  │ NaN │ ✅ 왼쪽에만 존재
   │ B │  2  │ 10  │ ✅ 양쪽 모두 존재
   │ C │  3  │ 20  │ ✅ 양쪽 모두 존재
   └───┴─────┴─────┘

═══════════════════════════════════

3️⃣ RIGHT (오른쪽 전체)
   how='right'
   
   ┌───┬─────┬─────┐
   │key│value│score│
   ├───┼─────┼─────┤
   │ B │  2  │ 10  │ ✅ 양쪽 모두 존재
   │ C │  3  │ 20  │ ✅ 양쪽 모두 존재
   │ D │ NaN │ 30  │ ✅ 오른쪽에만 존재
   └───┴─────┴─────┘

═══════════════════════════════════

4️⃣ OUTER (합집합)
   how='outer'
   
   ┌───┬─────┬─────┐
   │key│value│score│
   ├───┼─────┼─────┤
   │ A │  1  │ NaN │ ✅ 왼쪽에만
   │ B │  2  │ 10  │ ✅ 양쪽 모두
   │ C │  3  │ 20  │ ✅ 양쪽 모두
   │ D │ NaN │ 30  │ ✅ 오른쪽에만
   └───┴─────┴─────┘

실제 코드

# Inner (기본)
pd.merge(df_left, df_right, on='key', how='inner')

# Left
pd.merge(df_left, df_right, on='key', how='left')

# Right
pd.merge(df_left, df_right, on='key', how='right')

# Outer
pd.merge(df_left, df_right, on='key', how='outer')

 


6. 실전 팁

1) 언제 뭘 쓸까?

# 컬럼으로 합칠 때 → merge()
pd.merge(df1, df2, on='컬럼명')

# 인덱스로 합칠 때 → join() (더 간단)
df1.join(df2)

# 복잡한 조건 → merge() (더 유연)
pd.merge(df1, df2, left_on='col1', right_index=True)

2) 자주 쓰는 패턴

# 패턴 1: 기본 조인
pd.merge(df1, df2, on='id')

# 패턴 2: Left Join (모든 왼쪽 데이터 유지)
pd.merge(df1, df2, on='id', how='left')

# 패턴 3: 인덱스 조인
df1.join(df2)

# 패턴 4: 컬럼명 충돌 처리
pd.merge(df1, df2, on='id', suffixes=('_x', '_y'))

3) 주의사항

# ⚠️ 컬럼명 충돌 시 suffixes 사용
pd.merge(df1, df2, on='id', suffixes=('_old', '_new'))

# ⚠️ 인덱스를 컬럼으로 변환
df = df.reset_index()

# ⚠️ 컬럼을 인덱스로 변환
df = df.set_index('컬럼명')

 


비교 요약표

상황 추천 코드 예시
컬럼 기준 합치기 merge() pd.merge(df1, df2, on='id')
인덱스 기준 합치기 join() df1.join(df2)
복잡한 조건 merge() pd.merge(..., left_on, right_index)
간단한 조인 join() df1.join(df2)

핵심 정리

merge() - 만능 도구

# 컬럼 기준
pd.merge(df1, df2, on='컬럼명')

# 인덱스 기준
pd.merge(df1, df2, left_index=True, right_index=True)

# 혼합
pd.merge(df1, df2, left_on='col', right_index=True)

join() - 간편 도구

# 인덱스 기준 (기본)
df1.join(df2)

# 컬럼 기준 (왼쪽만)
df1.join(df2, on='컬럼명')

조인 타입

how='inner'  # 교집합 (기본)
how='left'   # 왼쪽 전체
how='right'  # 오른쪽 전체
how='outer'  # 합집합

요약

merge(): 컬럼으로 합칠 때 (대부분)

join(): 인덱스로 합칠 때 (간단)

how='left': 왼쪽 데이터 전부 유지

how='inner': 양쪽 모두 있는 것만

처음엔 merge()만 써도 OK!

 

'Data Science' 카테고리의 다른 글

Pandas | apply() 함수  (0) 2025.10.17
Pandas | 괄호 () 있고 없고의 차이  (0) 2025.10.15