13. 연결·병합·결합
🎯 이 장의 목표
- 여러 데이터프레임을 위아래·좌우로 연결한다(
concat) - 공통 열(키)을 기준으로 표를 병합한다(
merge) - 병합의 네 가지 방식(inner·outer·left·right)을 구분한다
💡 팁
현실에선 데이터가 여러 파일·표로 흩어져 있는 경우가 많습니다(주문 표 따로, 고객 표 따로). 이를 하나로 합치는 것이 이 장의 주제입니다.두 가지 합치기: 쌓기 vs 옆에 붙이기
데이터프레임을 합치는 방식은 크게 둘입니다.
flowchart TB
subgraph C["concat — 쌓기"]
direction TB
A1["표 A"] --> AB["A+B 위아래로"]
B1["표 B"] --> AB
end
subgraph M["merge — 키로 옆에 붙이기"]
direction LR
A2["주문 표"] --- key(("공통 키<br/>고객ID")) --- B2["고객 표"]
end
classDef box fill:#d0ebff,stroke:#1971c2,color:#000
classDef keyc fill:#fff3bf,stroke:#f59f00,color:#000
class A1,B1,AB,A2,B2 box
class key keyc
- concat(연결): 같은 형태의 표를 위아래로 쌓거나 좌우로 이어 붙임 (단순 연결)
- merge(병합): 공통 열(키)을 기준으로 두 표를 짝지어 옆으로 합침 (엑셀 VLOOKUP과 유사)
concat: 표 쌓기
pd.concat([표1, 표2])로 여러 표를 잇습니다. 기본은 위아래로(행 방향) 쌓습니다.
PYTHON
import pandas as pd jan = pd.DataFrame({"이름": ["철수", "영희"], "매출": [100, 200]}) feb = pd.DataFrame({"이름": ["민수", "지수"], "매출": [150, 250]}) result = pd.concat([jan, feb]) print(result)
실행 결과:
CODE
이름 매출 0 철수 100 1 영희 200 0 민수 150 1 지수 250
⚠️ 흔한 실수
흔한 함정 — 인덱스가 겹친다위 결과를 보면 인덱스가
0,1,0,1로 중복됩니다(각 표의 원래 번호를 유지하기 때문). 새로 0부터 매기려면 ignore_index=True를 줍니다.PYTHON
result = pd.concat([jan, feb], ignore_index=True) print(result)
실행 결과:
CODE
이름 매출 0 철수 100 1 영희 200 2 민수 150 3 지수 250
📌 핵심
append는 이제 없습니다예전 자료에는
df1.append(df2)라는 코드가 보일 수 있는데, 이 메서드는 Pandas 2.0에서 완전히 제거되었습니다. 지금은 반드시 pd.concat([df1, df2])를 쓰세요. (옛 코드를 따라 하다 AttributeError: 'DataFrame' object has no attribute 'append' 에러를 만나면 이것이 원인입니다.)좌우(열 방향)로 붙이려면 axis=1:
PYTHON
left = pd.DataFrame({"이름": ["철수", "영희"]}) right = pd.DataFrame({"점수": [85, 92]}) print(pd.concat([left, right], axis=1))
실행 결과:
CODE
이름 점수 0 철수 85 1 영희 92
merge: 키로 병합하기
merge는 공통 열(키)을 기준으로 두 표를 짝지어 합칩니다. 가장 강력하고 자주 쓰는 합치기입니다.
🔑 새 용어 — 키(key)
두 표를 이어 줄 공통의 기준 열입니다. 예를 들어 "주문 표"와 "고객 표"에 둘 다고객ID가 있으면, 그걸 키로 삼아 "어느 주문이 어느 고객의 것인지" 연결할 수 있습니다.
PYTHON
import pandas as pd # 주문 표: 어느 고객이 무엇을 샀나 orders = pd.DataFrame({ "고객ID": [1, 2, 3], "상품": ["노트북", "마우스", "키보드"] }) # 고객 표: 고객 정보 customers = pd.DataFrame({ "고객ID": [1, 2, 3], "이름": ["철수", "영희", "민수"] }) merged = pd.merge(orders, customers, on="고객ID") print(merged)
실행 결과:
CODE
고객ID 상품 이름 0 1 노트북 철수 1 2 마우스 영희 2 3 키보드 민수
on="고객ID"는 "고객ID를 기준 키로 삼아라"는 뜻입니다. 두 표의 같은 고객ID끼리 짝지어졌습니다.
병합의 네 가지 방식 (how)
키가 양쪽에 모두 있지 않을 때, 어느 쪽을 기준으로 남길지를 how로 정합니다. 예제 데이터를 살짝 바꿔 봅시다.
PYTHON
import pandas as pd orders = pd.DataFrame({ "고객ID": [1, 2, 4], # 4번 고객은 고객 표에 없음 "상품": ["노트북", "마우스", "모니터"] }) customers = pd.DataFrame({ "고객ID": [1, 2, 3], # 3번 고객은 주문이 없음 "이름": ["철수", "영희", "민수"] })
| how | 의미 | 남는 것 |
|---|---|---|
inner (기본) | 양쪽에 다 있는 키만 | 교집합 |
outer | 한쪽에라도 있는 키 전부 | 합집합 |
left | 왼쪽 표 기준 전부 | 왼쪽 다 + 맞는 오른쪽 |
right | 오른쪽 표 기준 전부 | 오른쪽 다 + 맞는 왼쪽 |
PYTHON
print(pd.merge(orders, customers, on="고객ID", how="inner"))
실행 결과 (양쪽 공통인 1,2번만):
CODE
고객ID 상품 이름 0 1 노트북 철수 1 2 마우스 영희
PYTHON
print(pd.merge(orders, customers, on="고객ID", how="outer"))
실행 결과 (1,2,3,4번 전부, 없는 칸은 NaN):
CODE
고객ID 상품 이름 0 1 노트북 철수 1 2 마우스 영희 2 3 NaN 민수 3 4 모니터 NaN
PYTHON
print(pd.merge(orders, customers, on="고객ID", how="left"))
실행 결과 (주문 표 기준, 4번은 이름 없음):
CODE
고객ID 상품 이름 0 1 노트북 철수 1 2 마우스 영희 2 4 모니터 NaN
💡 팁
어떤 how를 쓸까?가장 많이 쓰는 건
inner(공통만)와 left(왼쪽 기준 유지)입니다. "주문 표는 다 살리되 고객 정보를 붙이고 싶다"면 left가 적합합니다. 합쳤더니 행 수가 예상과 다르거나 NaN이 잔뜩 생겼다면, how 설정이 의도와 맞는지 가장 먼저 확인하세요.⚠️ 흔한 실수
흔한 함정 — 키가 중복되면 행이 불어난다한쪽 표에 같은 키가 여러 번 나오면, 병합 결과 행 수가 곱으로 불어날 수 있습니다. 병합 전
df["키"].duplicated().sum()으로 중복을 확인하는 습관이 좋습니다.🛠 미니 챌린지
PYTHON
import pandas as pd students = pd.DataFrame({ "학번": [101, 102, 103], "이름": ["가", "나", "다"] }) scores = pd.DataFrame({ "학번": [101, 102, 104], "점수": [90, 85, 70] })
- 두 표를
학번기준으로inner병합하세요. 몇 행이 나오나요? - 같은 두 표를
outer병합하세요. NaN이 어디에 생기나요? students를 기준(left)으로 점수를 붙이세요.
✅ 미니 챌린지 해설
PYTHON
# 1. inner — 공통 학번(101,102)만 print(pd.merge(students, scores, on="학번", how="inner"))
실행 결과 (2행):
CODE
학번 이름 점수 0 101 가 90 1 102 나 85
PYTHON
# 2. outer — 101,102,103,104 전부 print(pd.merge(students, scores, on="학번", how="outer"))
실행 결과:
CODE
학번 이름 점수 0 101 가 90.0 1 102 나 85.0 2 103 다 NaN ← 103은 점수 표에 없음 3 104 NaN 70.0 ← 104는 학생 표에 없음
PYTHON
# 3. left — 학생 표 기준 print(pd.merge(students, scores, on="학번", how="left"))
실행 결과:
CODE
학번 이름 점수 0 101 가 90.0 1 102 나 85.0 2 103 다 NaN
이 장에서 배운 것
pd.concat([표들])로 표를 위아래(기본)나 좌우(axis=1)로 잇는다.ignore_index=True로 번호를 새로 매긴다.append는 Pandas 2.0에서 제거됐으니concat을 쓴다.pd.merge(A, B, on="키")로 공통 열 기준 병합한다.how로 inner(공통)·outer(전부)·left·right를 정하며, inner와 left가 가장 흔하다.
✍️ 확인 문제
concat과merge의 차이를 한 문장으로 설명하세요.concat후 인덱스가0,1,0,1로 중복됐습니다. 어떻게 고치나요?- "왼쪽 표의 모든 행을 유지하면서 오른쪽 정보를 붙이고 싶다"면
how에 무엇을 줘야 하나요?
다음 장에서는 데이터를 그룹별로 묶어 요약하는 group-by와, 인덱스를 여러 층으로 쌓는 멀티인덱싱을 배웁니다. 데이터 요약의 핵심입니다.
👉 14. 멀티인덱싱과 그룹화