根据多列中的值从数据帧中删除重复的行


>>是>td style="text-align:right;">否>是>是
电子邮件 名称 已完成
aaa@xyz.com 01-07-2022 12:40:00 james
aaa@xyz.com 01-07-2022 12:10:00詹姆斯
aaa@xyz.com 01-07-2022 12:19:00 james
aaa@xyz.com 01-07-2022 12:30:00 james
bbb@xyz.com 02-07-2022 08:04:00 clark
bbb@xyz.com 02-07-2022 08:08:00 clark
bbb@xyz.com 2022年2月7日08:13:00 clark
bbb@xyz.com 02-07-2022 08:28:00 clark
df.sort_values('date').groupby(['email', 'name']).first().reset_index()

给出

名称日期
索引电子邮件完成
0aaa@xyz.comjames01-07-2022 12:10:00是
1bbb@xyz.comclark02-07-2022 08:04:00是

其他答案不一定满足要求:

我只想保留完成时的最早日期="是",并删除所有其他行。

它们只适用于给定正确行顺序的示例。我不会相信这一点。

为此,我们首先必须只选择具有completed == 'yes'的行。例如:

res = (
df[df.completed.eq('yes')]
.sort_values('date')
.groupby(['email', 'name'], as_index=False)
.first()
)

然而,假设可能有组(nameemail(不包含具有completed == 'yes'的行,但不应删除(即,在这种情况下只应考虑最近日期的要求(,则sort_values的逻辑应更改:

# sort first by df.completed == 'no', then by df.date in ascending order; 
# and then select the first row for each group (name, email)
res = (
df.sort_values(['completed', 'date'], 
key=lambda col: col.eq('no') if col.name == 'completed' else col)
.groupby(['email', 'name'], as_index=False)
.first()
)

输出:

>>> res
email   name                 date completed
0  aaa@xyz.com  james  01-07-2022 12:10:00       yes
1  bbb@xyz.com  clark  02-07-2022 08:04:00       yes

尝试.groupby,然后是.idxmin():

print(df[df.completed == "yes"].loc[df.groupby(["email", "name"])["date"].idxmin()])

打印:

email                date   name completed
1  aaa@xyz.com 2022-01-07 12:10:00  james       yes
4  bbb@xyz.com 2022-02-07 08:04:00  clark       yes

或者:按date然后按.drop_duplicates:对值进行排序

df = df[df.completed == "yes"].sort_values("date").drop_duplicates(["email", "name"], keep="first")
print(df)

EDIT:增加了df[df.completed == "yes"]部分。

最新更新