Pandas:如何合并两个有重复行的数据框

5

简短问题 在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 字段。
你对为什么其他行可能没有被填充有任何想法吗?
1个回答

7
你可以在与 how='left'merge 中使用 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期间,匹配将仅与此唯一名称进行


@RobertTownley 即使使用参数 how='left' 了吗?我是在一开始忘记加上去的。 - Ben.T
谢谢Ben,我刚刚编辑了更多信息。how='left'和deduping似乎正在起作用,但它并没有根据FULL_NAME字段进行一致匹配。相反,似乎只有在people.csv表中完全重复的行才会同时接收数据,而在FULL_NAME以外的字段上存在差异的行被视为不同的实体。你也觉得是这样吗? - Robert Townley
嗨Ben,我尝试复制一个简单的例子,但无法出现我的问题。我认为我的CSV文件有些问题,需要进一步研究。但你说得对,如果数据干净,你的方法确实做到了我想要的。感谢你的帮助! - Robert Townley
@RobertTownley 希望你能找到问题所在。你可以尝试使用 full['FULL_NAME'].str.strip() 或者类似的方法。你的数据中可能存在名字开头或结尾的“隐藏”空格! - Ben.T
1
重新回来说一声,确实是空格问题,去掉空格后就可以了,所以这个程序做到了我所希望的。 - Robert Townley
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接