Merge / Join 與資料關係
學習目標:使用 1:1、1:N、N:1 合併,辨識 many-to-many row explosion。
合併兩個表之前,最重要的問題不是「程式怎麼寫」,而是「這個 join 預期是什麼關係」。關係想錯了,程式一樣會跑,但結果的列數與意義會完全不對。
| 關係 | 意思 | 範例 |
|---|---|---|
| 1:1 | 兩個表在 join 鍵上都各只有一列 | 一家公司對應一筆最新的公司基本資料 |
| 1:N | 一個表的一列對應另一個表的多列 | 一家公司主檔對應它多個月份的月資料 |
| N:1 | 多列對應到另一個表的一列(1:N 反過來看) | 多個月份的月資料對應到同一家公司的主檔 |
master = pd.read_csv("DS102_Company_Master.csv")
# site_id 本身會在不同公司間重複,必須搭配 company_id 才是唯一的據點
joined = site_long.merge(master, on="company_id", how="left", validate="m:1")
joined.shape[0] == site_long.shape[0] # 1:N/N:1 的正確合併不應改變列數注意
假設 site_long 有 48 列,master 本來應該每個 company_id 只有一列。如果 master 不小心重複了同一個 company_id 兩次(例如同一家公司被匯入了兩次主檔),merge 之後的列數會變成 96 列而不是 48 列,每一筆月資料都被複製了一次,之後的加總會是正確答案的兩倍。
- 合併前先問:這應該是 1:1、1:N 還是 N:1?
- 在程式碼中用 merge(..., validate="1:1" / "1:m" / "m:1") 讓 pandas 幫你檢查,關係不符會直接報錯
- 合併後一定要檢查列數,並和「合併前的預期列數」核對,不能只看有沒有報錯
- 看到列數比預期多很多,先懷疑 join 鍵是否唯一,而不是急著使用結果
兩個表在同一個 join 鍵上都各自出現重複值,卻直接拿它們做 join。這樣做最主要的風險是什麼?