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
| 特性 | merge | concat |
|---|---|---|
| 用途 | 根據鍵值合併 | 堆疊串接 |
| 類似 SQL | JOIN | UNION |
| 對齊方式 | 按鍵值 | 按索引或順序 |