【问题标题】:Pandas: Merge two dataframes with duplicate rowsPandas:合并两个具有重复行的数据框
【发布时间】:2019-01-21 13:54:51
【问题描述】:

小问题 在 Pandas 中,合并两个数据帧最方便的方法是什么,以便左侧数据帧中的所有条目都从右侧数据帧接收第一个匹配值?

更长的问题 假设我有两个电子表格:people.csvorders.csvpeople.csv 包含有关此人的几列信息,而orders.csv 包含此人的全名,以及该人下的订单数。

我需要创建第三个 csv,output.csv,其中包含来自 people.csv 的所有列以及来自 output.csv 的列与两个电子表格中的一个列匹配(在一个中称为“FULL_NAME”,以及“ CUSTOMER_FULL_NAME”)

people.csv 按 FULL_NAME 字段排序,但包含重复行,因此 FULL_NAME 列中有多行带有“John Smith”。 orders.csv 中也有重复的行,但重复的数量不同(例如,people.csv 可能有 4 个 John Smith 条目,但 orders.csv 可能只有两个)。

如果我使用以下代码:

people = pd.read_csv('people.csv')
orders = pd.read_csv('orders.csv')
full = pd.merge(
    people,
    orders,
    left_on='FULL_NAME',
    right_on='CUSTOMER_FULL_NAME',
)
result.to_csv("output.csv")

... 我得到一个 CSV,其中在 FULL_NAME 字段中只有两行带有“John Smith”的行包含 John Smith 的订单数。正下方的行在该字段中没有值。这是因为 output.csv 只包含两行与 John Smith 匹配的值,而 people.csv 有 4 行。

Pandas 中是否有一种方便的方法可以将一个列的值设置为另一个数据框中的第一个匹配列,这样所有 4 个条目都包含来自orders.csv 的第一个匹配值?

编辑 我的脚本的完整当前版本,返回包含未使用预期值设置的行的 CSV:

import pandas as pd

community = pd.read_csv("orders.csv")
full = pd.read_csv("people.csv")
result = pd.merge(
    full,
    community.drop_duplicates(subset=['FULL_NAME'], keep='first'),
    left_on="CUSTOMER_FULL_NAME",
    right_on="FULL_NAME",
    how='left',
)
result.to_csv("output.csv")

所以我认为我在这里遗漏了其他内容,因为某些行以预期的方式匹配。这是输出文件中的一个示例:

ID      FULL_NAME   EMPLOYER            DIVISION            ORDER #
7350    John Smith  RiteAid             Clinical Research   25
7351    John Smith  RiteAid             Clinical Research   25
7352    John Smith  Costco              Sales   
7353    John Smith  Costco              Sales   

这个 John Smith 行在 orders.csv 文件中没有重复值,所以我认为这是有效的,因为其中有两行得到了它。但是,我没有在列出 Costco 而不是 RiteAid(或其他不同字段)的 John Smith 行上找到匹配项。这让我感到惊讶,因为我认为索引检查只针对 FULL_NAME 字段。

关于为什么其他行可能无法填写的任何想法?

【问题讨论】:

    标签: python pandas csv


    【解决方案1】:

    您可以在mergehow='left' 中对subset=['CUSTOMER_FULL_NAME'] 使用drop_duplicates,以保留people 中的所有行,例如:

    full = pd.merge(
        people,
        orders.drop_duplicates(subset=['CUSTOMER_FULL_NAME'], keep='first'), #here the differance
        left_on='FULL_NAME',
        right_on='CUSTOMER_FULL_NAME',
        how='left' #and add the how='left'
    )
    

    所以orders.drop_duplicates(subset=['CUSTOMER_FULL_NAME'], keep='first') 将只包含每个名称一次,并且在merge 期间,匹配将仅使用此唯一名称

    【讨论】:

    • 感谢 Ben,很高兴了解 drop_duplicates。不幸的是,这并没有让我很清楚:有了这个,现在只有 4 John Smith 行中的第一行包含 order # 列。有没有办法让所有 4 个匹配的行都具有来自去重订单数据帧的值?
    • @RobertTownley 即使使用参数how='left'?我一开始忘记后添加的
    • 谢谢 Ben,刚刚编辑了更多信息。 how='left' 和重复数据删除似乎确实有效,但它与 FULL_NAME 字段的匹配不一致。相反,似乎只有people.csv 表中相同重复的行都在接收数据,而在FULL_NAME 以外的字段上存在差异的行被视为不同的实体。这似乎也是你的情况吗?
    • @RobertTownley 确实不会出现您得到的行为。像这样,我看不出它不能按预期工作的任何原因。您能否从 fullcommunity 数据帧中添加相关行,看看我是否可以重现该行为?
    • 回过头来说这确实是一个空白问题,并且删除了空格,所以这确实符合我的希望
    猜你喜欢
    • 2017-01-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-12-16
    • 2015-03-21
    • 2021-03-22
    • 1970-01-01
    • 2020-07-07
    相关资源
    最近更新 更多