pandas Dataframe merge 後出現重複行

1. 初始化兩個dataframe

df_left = pd.DataFrame(
    columns=['no', 'name', 'age'],
    data=[['111', 'Andy', 19], ['222', 'Bob', 20], ['333', 'Cindy', 21]]
)

image-20220617115140702

df_right = pd.DataFrame(
    columns=['key_no', 'remark'],
    data=[['111', 'a'], ['111', 'b'], ['222', 'c']]
)

image-20220617115215487

注意到,df_leftno列是唯一的,df_rightkey_no列是有重複的

2. 合併兩個dataframe

res1 = pd.merge(left=df_left, right=df_right, left_on='no', right_on='key_no', how='left')

image-20220617115709656

左連接merge兩個df時,生成的df出現了重複行,原因是:df_leftno列有一行值爲 111, df_rightkey_no有兩行值爲 111,形成一對多的關係,因此出現重複行。

這個問題在官方文檔也有提及到:

image-20220617121709289

翻譯就是:

對重複鍵進行連接/合併可能導致返回的幀是行維度的乘法,這可能導致內存溢出。在加入大型 DataFrames 之前,用戶有責任管理鍵中的重複值。

3. 解決方式

3.1 解決方式1:

通過指定 validate='one_to_one'

If specified, checks if merge is of specified type.

  • “one_to_one” or “1:1”: check if merge keys are unique in both left and right datasets.
  • “one_to_many” or “1:m”: check if merge keys are unique in left dataset.
  • “many_to_one” or “m:1”: check if merge keys are unique in right dataset.
  • “many_to_many” or “m:m”: allowed, but does not result in checks.

如果拋異常,則說明沒有滿足一對一關係,則需要進行去重處理,比如drop_duplicates(要確保key重複時取哪個值)

例如:

from pandas.errors import MergeError

try:
    res2 = pd.merge(left=df_left, right=df_right, left_on='no', right_on='key_no', how='left', validate='one_to_one')
except MergeError as e:
    df_right = df_right.drop_duplicates(subset=['key_no'])  # 對 key_no 列去重,保留第一次出現的結果作爲值
    res2 = pd.merge(left=df_left, right=df_right, left_on='no', right_on='key_no', how='left', validate='one_to_one')

3.2 解決方式2

如果已經確定是一一對應的關係,則可以在 merge前就進行一次去重處理即可,而不需要去處理異常

例如:

df_right = df_right.drop_duplicates(subset=['key_no'])
res2 = pd.merge(left=df_left, right=df_right, left_on='no', right_on='key_no', how='left', validate='one_to_one')
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章