Pandas & NumPy Academy · 강의

pd.merge: 내부 조인과 외부 조인

공유 키 열을 기준으로 내부 조인과 외부 조인을 사용해 두 DataFrame을 병합하고 어떤 행이 유지되거나 삭제되는지 이해합니다.

레슨 2/413개 단계

pd.merge: 내부 조인과 외부 조인은(는) CoddyKit의 무료 Pandas & NumPy Academy 강의입니다. 이것은 4개 중 2번째 강의입니다. 아래에서 전체 강의를 무료로 읽을 수 있으며, 내장 코드 에디터와 24/7 AI 튜터와 함께 브라우저에서 직접 실습할 수 있습니다. 이 강의는 Pandas & NumPy Academy 학습 경로의 일부이며, 진행 상황이 웹과 CoddyKit 앱에 동기화됩니다. Pandas & NumPy Academy 강의에는 총 4개의 강의가 포함되어 있습니다.

Join이란 무엇인가요?

join은 공유 키 열을 기준으로 행을 일치시켜 두 DataFrames를 결합하는 기능으로, SQL의 JOIN 절과 같은 개념입니다. Pandas에서는 pd.merge()를 통해 join을 구현합니다. 데이터를 단순히 쌓기만 하는 pd.concat()과 달리, pd.merge()는 하나 이상의 열에서 값이 일치하는지를 기준으로 서로 다른 두 테이블의 행을 지능적으로 정렬합니다.

공유 키 열

병합이 작동하려면 두 DataFrames에 공유 값을 가진 열이 하나 이상 있어야 합니다. 이를 키 열이라고 합니다. 예를 들어 orders 테이블에 customer_id 열이 있고 customers 테이블에도 customer_id 열이 있을 수 있습니다. customer_id를 기준으로 병합하면 각 주문 행에 고객 세부 정보가 연결됩니다. 두 DataFrames에서 열 이름이 같다면 on 매개변수로 키를 지정합니다.

import pandas as pd

orders = pd.DataFrame({
    'order_id': [1, 2, 3, 4],
    'customer_id': [101, 102, 101, 103],
    'amount': [250, 80, 320, 150]
})

customers = pd.DataFrame({
    'customer_id': [101, 102, 104],
    'name': ['Alice', 'Bob', 'Diana']
})

Inner Join: 두 테이블의 교집합

inner join(기본값)은 키 값이 두 DataFrames 모두에 존재하는 행만 유지합니다. 어느 한 테이블에 있으면서 다른 테이블에 일치하는 키가 없는 행은 별도의 알림 없이 삭제됩니다. 주문 예제에서는 고객 103과 104가 다른 테이블에 일치하는 항목이 없으므로 inner join 결과에서 제외됩니다.

# Inner join (default): only matching rows from both
result = pd.merge(orders, customers, on='customer_id', how='inner')
print(result)
#    order_id  customer_id  amount   name
# 0         1          101     250  Alice
# 1         3          101     320  Alice
# 2         2          102      80    Bob
# Order 4 (customer 103) dropped - no match in customers
# Diana (customer 104) dropped - no match in orders

Outer Join: 두 테이블의 합집합

outer join(how='outer')은 두 DataFrames의 모든 행을 유지합니다. 다른 테이블에 일치하는 키가 없는 행은 누락된 열이 NaN으로 채워집니다. 일치하는 항목이 없는 레코드까지 보존하면서 두 데이터셋을 전체적으로 파악하고 싶을 때 유용합니다.

result = pd.merge(orders, customers, on='customer_id', how='outer')
print(result)
#    order_id  customer_id  amount   name
# 0       1.0          101   250.0  Alice
# 1       3.0          101   320.0  Alice
# 2       2.0          102    80.0    Bob
# 3       4.0          103   150.0    NaN  <- order with unknown customer
# 4       NaN          104     NaN  Diana  <- customer with no orders

이름이 다른 열을 기준으로 병합하기

각 DataFrame에서 키 열의 이름이 다르면 on 대신 left_on과 right_on을 사용합니다. Pandas는 왼쪽 DataFrame의 left_on 값과 오른쪽 DataFrame의 right_on 값이 같은 행을 일치시킵니다. 두 키 열은 모두 결과에 포함되므로, 나중에 중복되는 열 하나를 drop할 수 있습니다.

products = pd.DataFrame({
    'prod_id': [10, 20, 30],
    'name': ['Widget', 'Gadget', 'Doohickey']
})

order_lines = pd.DataFrame({
    'item_id': [10, 10, 20],
    'qty': [3, 1, 5]
})

result = pd.merge(order_lines, products,
                  left_on='item_id', right_on='prod_id')
print(result.drop(columns='prod_id'))
#    item_id  qty    name
# 0       10    3  Widget
# 1       10    1  Widget
# 2       20    5  Gadget

여러 열을 기준으로 병합하기

열의 조합(복합 키)을 기준으로 행을 일치시키려면 on에 목록을 전달합니다. 단일 열만으로는 고유하게 일치시킬 수 없을 때 흔히 사용하며, 예를 들어 year와 region을 함께 기준으로 병합할 수 있습니다. 행이 결과에 포함되려면 목록에 지정한 모든 열이 동시에 일치해야 합니다.

targets = pd.DataFrame({
    'year': [2023, 2023, 2024],
    'region': ['East', 'West', 'East'],
    'target': [100, 150, 120]
})
actuals = pd.DataFrame({
    'year': [2023, 2024, 2024],
    'region': ['East', 'East', 'West'],
    'actual': [95, 115, 80]
})

result = pd.merge(targets, actuals, on=['year', 'region'], how='inner')
print(result)
#    year region  target  actual
# 0  2023   East     100      95
# 1  2024   East     120     115

겹치는 열 이름 처리하기

두 DataFrames에 키가 아닌 동일한 이름의 열이 있으면 Pandas는 서로 구분할 수 있도록 접미사를 추가합니다. 기본 접미사는 왼쪽 열에 _x, 오른쪽 열에 _y입니다. suffixes 매개변수로 이를 원하는 값으로 설정하면 더 의미 있는 이름을 만들고 결과에서 혼동을 줄일 수 있습니다.

df_a = pd.DataFrame({'id': [1, 2], 'value': [10, 20]})
df_b = pd.DataFrame({'id': [1, 2], 'value': [100, 200]})

# Default suffixes
print(pd.merge(df_a, df_b, on='id'))
#    id  value_x  value_y

# Custom suffixes
print(pd.merge(df_a, df_b, on='id', suffixes=('_budget', '_actual')))
#    id  value_budget  value_actual

예상치 못한 중복 확인하기

병합에서 흔히 발생하는 문제는 예상치 못한 행 증가입니다. 두 DataFrames의 키 열에 중복 값이 있으면 병합 결과에는 일치하는 모든 행의 카테시안 곱이 생성됩니다. 병합 후에는 항상 행 수를 확인하십시오. 예상보다 많다면 df.duplicated(subset=['key']).sum()으로 키 열의 중복을 조사하십시오.

# Both tables have duplicate keys -> cartesian product
left = pd.DataFrame({'id': [1, 1], 'val_l': ['a', 'b']})
right = pd.DataFrame({'id': [1, 1], 'val_r': ['x', 'y']})

result = pd.merge(left, right, on='id')
print(len(result))  # 4 rows! (2x2 cartesian product)
print(result)
#    id val_l val_r
# 0   1     a     x
# 1   1     a     y
# 2   1     b     x
# 3   1     b     y

안전을 위한 validate 매개변수

validate 매개변수를 전달하면 병합에서 관계 제약 조건을 적용하고, 이를 위반할 경우 오류를 발생시킬 수 있습니다. 'one_to_one'은 두 테이블 모두에서 키가 고유해야 함을 의미하고, 'one_to_many'는 왼쪽 테이블에서만 키가 고유해야 함을 의미하며, 'many_to_one'은 오른쪽 테이블에서만 키가 고유해야 함을 의미합니다. 이는 데이터 품질 문제를 조기에 발견하는 뛰어난 방어적 코딩 방법입니다.

# Safe merge: validate that customer_id is unique in customers
try:
    result = pd.merge(orders, customers,
                      on='customer_id',
                      how='inner',
                      validate='many_to_one')
    print('Merge OK, shape:', result.shape)
except Exception as e:
    print('Merge error:', e)

indicator로 포함 범위 확인하기

indicator=True를 전달하면 결과에 _merge 열이 추가되어 각 행의 출처를 보여 줍니다. 값은 'left_only', 'right_only', 'both' 중 하나입니다. outer join 후 어떤 레코드가 일치했고 어떤 레코드가 일치하지 않았는지 확인하는 데 유용하며, indicator 열을 삭제하기 전에 데이터 품질을 감사할 수 있습니다.

result = pd.merge(orders, customers, on='customer_id',
                  how='outer', indicator=True)
print(result['_merge'].value_counts())
# both           3
# left_only      1  <- orders with no customer record
# right_only     1  <- customers with no orders

# Find unmatched orders
print(result[result['_merge'] == 'left_only'])

Inner와 Outer 요약

두 join 유형을 요약하면 다음과 같습니다. inner join은 교집합을 제공하므로 두 DataFrames에서 키가 일치하는 행만 포함합니다. outer join은 합집합을 제공하므로 두 DataFrames의 모든 행을 포함하고 일치하는 항목이 없으면 NaN을 사용합니다. 참고로 left join은 왼쪽 DataFrame의 모든 행을 보존하고, right join은 오른쪽 DataFrame의 모든 행을 보존합니다. 이 유형들은 다음 레슨에서 다룹니다.

# Quick reference
# how='inner'  -> intersection: only matched rows
# how='outer'  -> union: all rows from both, NaN for no match
# how='left'   -> all left rows + matched right rows
# how='right'  -> all right rows + matched left rows

# Most common: inner (default) for enrichment, left for preserving records

빠른 확인

이번 레슨에서 배운 pd.merge의 inner 및 outer join에 대한 이해도를 확인해 보십시오.

레슨 복습

이번 레슨에서는 pd.merge()에서 how='inner'를 사용하면 두 DataFrames의 일치하는 행만 유지하고, how='outer'를 사용하면 일치하지 않는 경우 NaN을 사용하여 모든 행을 유지한다는 점을 배웠습니다. 또한 on은 공유 키를 지정하고, left_on/right_on은 서로 다른 열 이름을 처리하며, indicator 매개변수는 어떤 행이 일치했는지 감사하는 데 도움을 줍니다. 다음으로는 한쪽의 모든 행을 보존하는 left 및 right join을 살펴보겠습니다.

무료로 시작

AI 튜터와 함께 Python을(를) 배우세요 — 무료

브라우저에서 실제 코드를 작성하고 실행하며, 24/7 AI 튜터로부터 즉각적인 도움을 받고, 웹이나 앱에서 중단한 부분부터 계속 학습하세요.

코스
30
레슨
120

자주 묻는 질문

“pd.merge: 내부 조인과 외부 조인” 강의는 무료인가요?

네 — “pd.merge: 내부 조인과 외부 조인” 전체 내용을 이 웹사이트에서 무료로 읽을 수 있습니다. 인터랙티브하게 실습하려면(내장 코드 에디터와 24/7 AI 튜터), CoddyKit PRO로 업그레이드하면 Pandas & NumPy Academy 강의 전체를 잠금 해제할 수 있습니다. Pandas & NumPy Academy 강의에는 총 4개의 강의가 포함되어 있습니다.

“pd.merge: 내부 조인과 외부 조인”에서 뭘 배우나요?

공유 키 열을 기준으로 내부 조인과 외부 조인을 사용해 두 DataFrame을 병합하고 어떤 행이 유지되거나 삭제되는지 이해합니다. 브라우저에서 직접 실행하는 실습 코드로 Pandas & NumPy Academy을(를) 배우며, 24/7 AI 튜터가 강의를 진행하면서 질문에 답변해줍니다.

Pandas & NumPy Academy을(를) 시작하는 데 경험이 필요한가요?

사전 경험은 필요하지 않습니다. CoddyKit의 Pandas & NumPy Academy은(는) 초급자부터 고급 학습자까지를 위해 구성되어 있으므로, 여기서 시작하거나 처음부터 시작할 수 있으며 자신의 속도대로 진행할 수 있습니다. 이것은 4개 중 2번째 강의입니다.

“pd.merge: 내부 조인과 외부 조인” 강의는 얼마나 걸리나요?

대부분의 CoddyKit 강의는 약 5~10분이 소요됩니다. 각 강의는 간결하고 인터랙티브하여 꾸준한 진행이 가능하며, 웹과 앱에서 중단한 부분부터 바로 시작할 수 있습니다.

이 Pandas & NumPy Academy 강의에서 코드를 작성하고 실행할 수 있나요?

네. 모든 Pandas & NumPy Academy 강의에는 내장 코드 에디터가 포함되어 있으므로, 브라우저에서 바로 실제 코드를 작성하고 실행한 후 즉시 AI 피드백을 받을 수 있습니다 — 로컬 설정이 필요 없습니다.

이 강의의 모든 강의

  1. DataFrame 쌓기에 pd.concat 사용하기
  2. pd.merge: 내부 조인과 외부 조인
  3. 왼쪽 조인과 오른쪽 조인
  4. 인덱스로 조인하기
← Pandas & NumPy Academy(으)로 돌아가기