【问题标题】:Pandas loop over 2 dataframe and drop duplicatesPandas 循环遍历 2 个数据帧并删除重复项
【发布时间】:2021-11-18 03:46:29
【问题描述】:

我有 2 个带有一些随机数的 csv 文件,如下所示:

csv1.csv

0       906018
1       007559
2       910475
3       915104
4       600393
         ...  
5070    907525
5071    903079
5072    001910
5073    909735
5074    914861

length 5075

csv2.csv

0         5555
1         7859
2       501303
3       912414
4       913257
         ...  
7497    915031
7498    915030
7499    915033
7500    902060
7501    915038

length 7502

csv1 中的一些元素存在于csv2 中,但我不知道具体是哪一个,我想提取这些唯一值。所以我的想法是开始将 2 个数据框合并在一起,然后删除重复项。

所以我写了以下代码:

import pandas as pd
import csv


unique_users = pd.read_csv('./csv1.csv')
unique_users['id']

identity = pd.read_csv('./csv2.csv')
identityNumber = identity['IDNumber']
identityNumber


df = pd.concat([identityNumber, unique_users])

直到这里一切都很完美,df的长度是2个长度的总和,但我意识到我卡住的部分。

df concat 它完成了它的工作并根据索引进行了 concat,所以现在我有大量的 NaN。

当我使用代码时:

final_result = df.drop_duplicates(keep=False)

数据框不会丢弃任何值,因为 df 结构现在如下所示:

Identitynumber.    ID
5555               NaN

所以我猜 drop duplicate 正在寻找相同的确切值,但由于它们不存在,它只是保留它。

所以我想做的是循环遍历两个数据帧,如果 csv1 中的值存在于 csv2 中,我希望它们被删除。

有人可以帮忙吗?

如果您需要更多信息,请告诉我。

更新:

我想我找到了不工作的原因,但我不知道如何解决这个问题。

我的 csv1 看起来像这样:

id
906018,
007559,
910475,
915104,
600393,
007992,
502313,
004609,
910017,
007954,
006678,

在 Jupiter notebook 中,当我打开 csv 时,它看起来是这样的。


        id
906018  NaN
007559  NaN
910475  NaN
915104  NaN
600393  NaN
... ...
907525  NaN
903079  NaN
001910  NaN
909735  NaN
914861  NaN

我不明白为什么将 id 视为 NaN。

事实上,我尝试在 csv2 中添加一个新列,并作为值传递来自 csv1 的 id..并且我可以确认它们都是 NaN。 所以我相信问题的根源肯定是这个,而不是反映在所有其他事件上。 谁能帮助了解我如何解决这个问题?

【问题讨论】:

  • 我是否理解正确,您想在 df2 中查找 df1 中已经存在的值,然后将其删除?有几个相似(但不同)的操作,所以清晰很重要
  • @anon01 是的,在 df1 我有 5075 个值,在 df2 我有 7502。在 df2 我有大部分值在 df1..所以如果我删除重复项 (7502 - 5075) 我应该只有 dinstinc
  • 但是现在在我的输出中我有 9000 和 plus 作为输出。这意味着它没有删除所有重复的值
  • @NaydenVan 看起来它是由尾随逗号引起的。由于每行末尾有一个逗号,Pandas 预计会有两列,并假设数字是索引。删除结尾的逗号,它应该可以工作,但很难确定。你的两个 csv 文件是这样的吗?

标签: pandas dataframe


【解决方案1】:

这将删除两个数据帧之间的重复项,并将所有记录保存在一个数据帧 df 中。

df = pandas.concat([df1,df2]).drop_duplicates().reset_index(drop=True)

【讨论】:

  • 如果两个数据框的列名不同,这仍然会产生NaN。
【解决方案2】:

你得到NaN,因为当你连接时,Pandas 不知道你想对两个数据框的不同列名做什么。您的一个数据框有一个 IdentityNumber 列,另一个有一个 ID 列。 Pandas 无法确定您想要什么,因此它将两列都放入结果数据框中。

试试这个:

pd.concat([df1["IDNumber"], df2["ID"]]).drop_duplicates().reset_index(drop=True)

【讨论】:

  • 感谢您的回复。我尝试了这个解决方案,最终输出长度为 7502..a 开头。结果我预计会有 2400 左右。
  • @NaydenVan 看到我的编辑。如果您只想获取这两列的唯一值,请直接在连接中使用它们的列名。
  • 我尝试了edit swell,结果总是超过9000。:(
  • 我刚刚更新了我的帖子,我认为这是问题的根源
【解决方案3】:

您可以使用 df.merge() 实现此目的:

# Data samples
data_1 = {'col_a': [906018,7559,910475,915104,600393,907525,903079,1910,909735,914861]}
data_2 = {'col_b': [5555,7859,914861,912414,913257,915031,1910,915104,7559,915038]}

df1 = pd.DataFrame(data_1)
df2 = pd.DataFrame(data_2)

# using isin() method
unique_vals = df1.merge(df2, right_on='col_b', left_on='col_a')['col_a']
new_df1 = df1[~df1.col_a.isin(unique_vals)]

# another approach
new_df1 = df1[df1.merge(df2, right_on='col_b', left_on='col_a', how='left')['col_b'].isna()]

print(new_df1)
#    col_a
# 0  906018
# 2  910475
# 4  600393
# 5  907525
# 6  903079
# 8  909735

【讨论】:

  • 非常感谢。这种方法奏效了。你能这么好,请解释一下背后的过程吗?这一点我没完全理解`right_on='col_b', left_on='col_a')['col_a']`
  • 当然,我会在一个小时内完成(我无法访问我的笔记本电脑 atm :))。同时,如果我的回答有效,您介意批准和投票吗?
  • 所以基本上,您将这些数据框合并到每个数据框的目标列上 (col_a of df1 and col_b of df2)。然后,您将拥有一个合并的数据框,其中合并数据框的 col_a 列包含 df2 的所有常见值。然后,我们使用否定运算符使用布尔索引排除这些值。
猜你喜欢
  • 2012-09-22
  • 2011-11-30
  • 2017-12-20
  • 2020-11-21
  • 2021-05-16
  • 2010-09-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多