BioPlayground

🧬
목록으로

DataFrame 병합 — merge와 concat

pandas에서 두 DataFrame을 합치는 merge, concat, join의 차이와 사용법을 배웁니다.

중급
|
10
|
검증 완료 (2026-07)
mergeconcatDataFrame 병합inner joinleft join
진행률0/11 (0%)

DataFrame 병합 — merge와 concat

이 토픽을 마치면

merge와 concat의 차이를 명확히 구분하고, inner/left/right/outer join을 이해하며, 실무에서 올바른 병합 방식을 선택할 수 있습니다.


언제 병합이 필요한가

실무 데이터는 대부분 여러 테이블에 분산되어 있습니다.

text
users 테이블:           orders 테이블:
┌────┬──────┐           ┌─────────┬────────┬────────┐
│ id │ name │           │ order_id│ user_id│ amount │
├────┼──────┤           ├─────────┼────────┼────────┤
│  1 │ Alice│           │    101  │    1   │   5000 │
│  2 │ Bob  │           │    102  │    2   │   3000 │
│  3 │ Carol│           │    103  │    1   │   7000 │
└────┴──────┘           └─────────┴────────┴────────┘

"각 사용자별 주문 합계"를 구하려면 두 테이블을 합쳐야 합니다. 이것이 **병합(merge)**입니다.


merge — 키를 기준으로 합치기

merge()는 SQL의 JOIN과 동일합니다. **공통 컬럼(키)**을 기준으로 두 DataFrame을 합칩니다.

python
import pandas as pd
users = pd.DataFrame({
"user_id": [1, 2, 3],
"name": ["Alice", "Bob", "Carol"]
})
orders = pd.DataFrame({
"order_id": [101, 102, 103],
"user_id": [1, 2, 1],
"amount": [5000, 3000, 7000]
})
result = pd.merge(users, orders, on="user_id")
print(result)
# user_id name order_id amount
# 0 1 Alice 101 5000
# 1 1 Alice 103 7000
# 2 2 Bob 102 3000

Alice는 주문이 2개이므로 2행으로 나타납니다. Carol은 주문이 없으므로 결과에 없습니다 — 이것이 inner join의 기본 동작입니다.


Join 종류

python
users = pd.DataFrame({
"user_id": [1, 2, 3],
"name": ["Alice", "Bob", "Carol"]
})
orders = pd.DataFrame({
"order_id": [101, 102, 104],
"user_id": [1, 2, 4],
"amount": [5000, 3000, 8000]
})
# user_id=3(Carol)은 주문 없음, user_id=4는 사용자 테이블에 없음

Inner Join (기본값)

양쪽 모두에 있는 키만.

python
pd.merge(users, orders, on="user_id", how="inner")
# user_id name order_id amount
# 0 1 Alice 101 5000
# 1 2 Bob 102 3000

Left Join

왼쪽 DataFrame의 모든 행 유지. 오른쪽에 없으면 NaN.

python
pd.merge(users, orders, on="user_id", how="left")
# user_id name order_id amount
# 0 1 Alice 101.0 5000.0
# 1 2 Bob 102.0 3000.0
# 2 3 Carol NaN NaN

Carol은 주문이 없지만 결과에 포함됩니다.

Right Join

오른쪽 DataFrame의 모든 행 유지.

python
pd.merge(users, orders, on="user_id", how="right")
# user_id name order_id amount
# 0 1 Alice 101 5000
# 1 2 Bob 102 3000
# 2 4 NaN 104 8000

user_id=4는 사용자 테이블에 없지만 결과에 포함됩니다.

Outer Join

양쪽 모든 행 유지.

python
pd.merge(users, orders, on="user_id", how="outer")
# user_id name order_id amount
# 0 1 Alice 101.0 5000.0
# 1 2 Bob 102.0 3000.0
# 2 3 Carol NaN NaN
# 3 4 NaN 104.0 8000.0

키 컬럼 이름이 다를 때

python
users = pd.DataFrame({"id": [1, 2], "name": ["Alice", "Bob"]})
orders = pd.DataFrame({"customer_id": [1, 2], "amount": [5000, 3000]})
# left_on / right_on 사용
pd.merge(users, orders, left_on="id", right_on="customer_id")
# id name customer_id amount
# 0 1 Alice 1 5000
# 1 2 Bob 2 3000

concat — 단순히 쌓기

concat()는 키 매칭 없이 DataFrame을 위아래 또는 좌우로 붙입니다.

위아래 (axis=0, 기본값)

python
jan = pd.DataFrame({"product": ["A", "B"], "sales": [100, 200]})
feb = pd.DataFrame({"product": ["A", "B"], "sales": [150, 250]})
quarterly = pd.concat([jan, feb], ignore_index=True)
# product sales
# 0 A 100
# 1 B 200
# 2 A 150
# 3 B 250

ignore_index=True를 쓰면 인덱스가 0부터 재설정됩니다. 안 쓰면 원래 인덱스(0,1,0,1)가 중복됩니다.

좌우 (axis=1)

python
info = pd.DataFrame({"name": ["Alice", "Bob"], "age": [30, 25]})
scores = pd.DataFrame({"math": [90, 85], "english": [88, 92]})
combined = pd.concat([info, scores], axis=1)
# name age math english
# 0 Alice 30 90 88
# 1 Bob 25 85 92

merge vs concat — 언제 뭘 쓰는가

mergeconcat
목적공통 키로 매칭해서 합치기단순히 쌓기/붙이기
SQL 비유JOINUNION
키 필요Yes (on, left_on/right_on)No
방향좌우 (열 추가)위아래 또는 좌우
사용 사례사용자 + 주문, 상품 + 카테고리월별 데이터 합치기, 분할 파일 합치기
text
"사용자와 주문을 연결" → merge (키 매칭)
"1월 데이터와 2월 데이터를 이어붙이기" → concat (단순 쌓기)

merge 주의사항 — 중복과 키 불일치

다대다 병합의 행 폭발

python
# 한 user_id에 주문이 여러 개, 배송도 여러 개
orders = pd.DataFrame({
"user_id": [1, 1, 1],
"order_id": [101, 102, 103]
})
shipments = pd.DataFrame({
"user_id": [1, 1],
"shipment_id": ["S1", "S2"]
})
result = pd.merge(orders, shipments, on="user_id")
print(len(result)) # 6! (3 × 2 = 카르테시안 곱)

양쪽에 같은 키가 여러 개 있으면 모든 조합이 생성됩니다. 3행 × 2행 = 6행. 대규모 데이터에서 이런 병합은 메모리를 폭발시킵니다. validate 파라미터로 방지할 수 있습니다:

python
pd.merge(orders, shipments, on="user_id", validate="many_to_one")
# MergeError: Merge keys are not unique in right dataset

실전 패턴 — 여러 파일 합치기

python
import os
import pandas as pd
data_dir = "monthly_reports"
all_dfs = []
for filename in sorted(os.listdir(data_dir)):
if filename.endswith(".csv"):
filepath = os.path.join(data_dir, filename)
df = pd.read_csv(filepath)
df["source_file"] = filename
all_dfs.append(df)
combined = pd.concat(all_dfs, ignore_index=True)
print(f"Total rows: {len(combined)}")

월별 CSV 파일을 하나로 합치는 패턴입니다. source_file 컬럼을 추가해서 어느 파일에서 왔는지 추적할 수 있습니다.


핵심 정리

함수용도핵심 파라미터
merge()키 기반 병합 (JOIN)on, how, left_on/right_on
concat()단순 쌓기 (UNION)axis, ignore_index
Join포함 범위
inner양쪽 모두에 있는 키만
left왼쪽 전부 + 오른쪽 매칭
right오른쪽 전부 + 왼쪽 매칭
outer양쪽 모두 (없으면 NaN)

데이터 분석의 80%는 올바른 테이블을 올바른 방식으로 합치는 것입니다. merge와 concat의 차이, 4가지 join의 동작을 명확히 이해하면, 데이터 전처리에서 가장 흔한 실수(중복 행, NaN 폭발, 키 불일치)를 예방할 수 있습니다.