使用布尔索引根据匹配的列值删除重复项

Removing duplicates based on matching column values with boolean indexing

提问人:Stijn 提问时间:3/29/2022 最后编辑:Stijn 更新时间:3/29/2022 访问量:234

问:

合并两个 DF 后,我有以下数据集:

DB_ID x_val y_val
x01系列 405 407
x01系列 405 405
x02系列 308 306
x02系列 308 308
x03系列 658 658
x03系列 658 660
x04系列 没有 658
x04系列 没有 660
x05系列 658 660
x06系列 660 660

y 表包含左联接变量的多个值(不包括在表中),导致每个唯一DB_ID(字符串变量,不在 df 索引中)多行。

问题在于只有一行是正确的,其中x_val和y_val匹配。我尝试使用以下代码删除重复项:df= df[~df['DB_ID'].duplicated() | combined['x_val'] != combined['y_val']]

然而,这是行不通的。我正在寻找一种解决方案来实现以下结果:

DB_ID x_val y_val
x01系列 405 405
x02系列 308 308
x03系列 658 658
x04系列 没有 658
x05系列 658 660
x06系列 660 660
pandas 数据帧 布尔逻辑

评论

0赞 jezrael 3/29/2022
你能添加一些不重复的行和预期的输出吗?例如DB_IDx04 100 100
0赞 jezrael 3/29/2022
另外,如果添加,那么每个 2 个重复的行会发生什么?x01 405 405x01
0赞 jezrael 3/29/2022
如果添加会发生什么?x05 200 300
0赞 Stijn 3/29/2022
@jezrael,大功告成!这是一个非常棘手的表,x_val和y_val用于检查是否使用了正确的连接变量。x_val 和 y_val 是一个对象 ID 变量,两个表之间应该匹配。如果它们不匹配,我会在另一列中用特定值进行描述。因此,不应删除这些值。x04 特别棘手,因为 X 没有可用的对象 ID,但根据联接值返回两个条目。在这种情况下,保留哪一行并不重要。但我不能允许任何DB_ID重复。保持匹配x_val和y_val具有最强的偏好。
0赞 Stijn 3/29/2022
@jezrael添加变量作为合并条件在我的情况下不起作用,因为 x 表有时缺少该变量,但基于连接变量,即使对于 x04,也可能返回两个变量,其中 x_val = None 或 NaN

答:

2赞 jezrael 3/29/2022 #1

想法是比较两列不相等,然后按以下方式对重复项进行排序和重新分配:DB_ID

df = (df.assign(new = df['x_val'].ne(df['y_val']))
        .sort_values(['DB_ID','new'])
        .drop_duplicates('DB_ID')
        .drop('new', axis=1))
print (df)
  DB_ID x_val y_val
1   x01   405   405
3   x02   308   308
4   x03   658   658
6   x04  None   658
8   x05   658   660
9   x06   660   660

如果需要相等的 s 或 s,请使用:NaNNone

df = (df.assign(new = df['x_val'].fillna('same').ne(df['y_val'].fillna('same')))
        .sort_values(['DB_ID','new'])
        .drop_duplicates('DB_ID')
        .drop('new', axis=1))

评论

1赞 Stijn 3/29/2022
太棒了,谢谢!
0赞 Corralien 3/29/2022 #2

也许,您可以简单地使用:

df = df[df['x_val'] == df['y_val']]
print(df)

# Output
  DB_ID  x_val  y_val
1   x01    405    405
3   x02    308    308
4   x03    658    658

我认为你不需要,但如果你想确保每个只有一个实例,你可以附加drop_duplicatesduplicatedDB_ID.drop_duplicates('DB_ID')

df = df[df['x_val'] == df['y_val']].drop_duplicates('DB_ID')
print(df)

# Output
  DB_ID  x_val  y_val
1   x01    405    405
3   x02    308    308
4   x03    658    658