Pandas merge

merge() 函數用於根據一個或多個鍵(key)合併兩個 DataFrame,類似於 SQL 的 JOIN 操作。

基本用法

import pandas as pd

# 使用者資料
users = pd.DataFrame({
    'user_id': [1, 2, 3],
    'name': ['Alice', 'Bob', 'Charlie']
})

# 訂單資料
orders = pd.DataFrame({
    'order_id': [101, 102, 103, 104],
    'user_id': [1, 2, 1, 4],
    'amount': [100, 200, 150, 300]
})

# 合併
result = pd.merge(users, orders, on='user_id')
print(result)
   user_id     name  order_id  amount
0        1    Alice       101     100
1        1    Alice       103     150
2        2      Bob       102     200

預設是 inner join,只保留兩邊都有的資料。

合併類型(how 參數)

inner join(內連接)

只保留兩邊都有匹配的資料(預設):

result = pd.merge(users, orders, on='user_id', how='inner')

left join(左連接)

保留左邊表格的所有資料:

result = pd.merge(users, orders, on='user_id', how='left')
print(result)
   user_id     name  order_id  amount
0        1    Alice     101.0   100.0
1        1    Alice     103.0   150.0
2        2      Bob     102.0   200.0
3        3  Charlie       NaN     NaN

Charlie 沒有訂單,但仍保留。

right join(右連接)

保留右邊表格的所有資料:

result = pd.merge(users, orders, on='user_id', how='right')
print(result)
   user_id   name  order_id  amount
0        1  Alice       101     100
1        1  Alice       103     150
2        2    Bob       102     200
3        4    NaN       104     300

user_id=4 的訂單沒有對應的使用者,但仍保留。

outer join(外連接)

保留兩邊所有的資料:

result = pd.merge(users, orders, on='user_id', how='outer')
print(result)
   user_id     name  order_id  amount
0        1    Alice     101.0   100.0
1        1    Alice     103.0   150.0
2        2      Bob     102.0   200.0
3        3  Charlie       NaN     NaN
4        4      NaN     104.0   300.0

不同欄位名稱

當兩個表格的鍵欄位名稱不同時:

users = pd.DataFrame({
    'id': [1, 2, 3],
    'name': ['Alice', 'Bob', 'Charlie']
})

orders = pd.DataFrame({
    'order_id': [101, 102],
    'user_id': [1, 2],
    'amount': [100, 200]
})

# 使用 left_on 和 right_on
result = pd.merge(users, orders, left_on='id', right_on='user_id')
print(result)
   id   name  order_id  user_id  amount
0   1  Alice       101        1     100
1   2    Bob       102        2     200

多個鍵合併

df1 = pd.DataFrame({
    'year': [2023, 2023, 2024],
    'city': ['Taipei', 'Tokyo', 'Taipei'],
    'sales': [100, 200, 150]
})

df2 = pd.DataFrame({
    'year': [2023, 2024],
    'city': ['Taipei', 'Taipei'],
    'target': [90, 140]
})

# 使用多個鍵
result = pd.merge(df1, df2, on=['year', 'city'])
print(result)

處理重複欄位名稱

當兩個表格有同名但不是鍵的欄位時:

df1 = pd.DataFrame({
    'id': [1, 2],
    'value': [10, 20]
})

df2 = pd.DataFrame({
    'id': [1, 2],
    'value': [100, 200]
})

result = pd.merge(df1, df2, on='id')
print(result)
   id  value_x  value_y
0   1       10      100
1   2       20      200

自訂後綴:

result = pd.merge(df1, df2, on='id', suffixes=('_left', '_right'))

使用索引合併

df1 = pd.DataFrame({
    'value1': [10, 20]
}, index=[1, 2])

df2 = pd.DataFrame({
    'value2': [100, 200]
}, index=[1, 3])

# 使用索引作為合併鍵
result = pd.merge(df1, df2, left_index=True, right_index=True, how='outer')

驗證合併

# 確保合併鍵是一對一
result = pd.merge(df1, df2, on='id', validate='one_to_one')

# 確保左邊是唯一的
result = pd.merge(df1, df2, on='id', validate='one_to_many')

# 確保右邊是唯一的
result = pd.merge(df1, df2, on='id', validate='many_to_one')

indicator 參數

顯示每一列的資料來源:

result = pd.merge(users, orders, on='user_id', how='outer', indicator=True)
print(result)
   user_id     name  order_id  amount      _merge
0        1    Alice     101.0   100.0        both
1        1    Alice     103.0   150.0        both
2        2      Bob     102.0   200.0        both
3        3  Charlie       NaN     NaN   left_only
4        4      NaN     104.0   300.0  right_only

實際應用

關聯式資料合併

# 使用者
users = pd.DataFrame({
    'user_id': [1, 2, 3],
    'name': ['Alice', 'Bob', 'Charlie']
})

# 訂單
orders = pd.DataFrame({
    'order_id': [101, 102, 103],
    'user_id': [1, 1, 2],
    'product_id': [201, 202, 201]
})

# 產品
products = pd.DataFrame({
    'product_id': [201, 202],
    'product_name': ['Widget', 'Gadget'],
    'price': [100, 200]
})

# 多表合併
result = (orders
    .merge(users, on='user_id')
    .merge(products, on='product_id'))
print(result)

找出沒有訂單的使用者

result = pd.merge(users, orders, on='user_id', how='left', indicator=True)
no_orders = result[result['_merge'] == 'left_only']

merge vs concat

特性mergeconcat
用途根據鍵值合併堆疊串接
類似 SQLJOINUNION
對齊方式按鍵值按索引或順序