熊猫:分组并根据条件在每个组中删除行

Posted

技术标签:

【中文标题】熊猫:分组并根据条件在每个组中删除行【英文标题】:Pandas: Groupby and drop rows in each group based on conditon 【发布时间】:2021-07-18 18:13:28 【问题描述】:

我有一个数据框:

   Name  StartPoint  EndPoint  isDelivered Customer
0     A           1         4            0       C1
1     A           1         4            0       C1
2     A           2         5            1       C1
3     A           3         5            0       C1
4     A           3         6            0       C1
5     A           3         6            1       C1
6     B           1         4            0       C2
7     B           1         4            0       C2
8     B           2         5            1       C2
9     B           3         5            1       C2
10    B           3         6            1       C2
11    B           3         8            0       C2
12    B           3         8            1       C2

我想按Name 分组,每个组应该有满足以下条件的行:

    StartPoint 列中的最小值 EndPoint 列中的最大值和isDelivered 列中的值 1

这就是我所做的:

groups = df.groupby(['Name']).StartPoint
groups1 = df.groupby(['Name']).EndPoint
min_StartPoint = groups.transform(min)
max_EndPoint = groups1.transform(max)
df1 = df[(df.StartPoint==min_StartPoint)|(df.EndPoint==max_EndPoint)]

得到的结果是:

   Name  StartPoint  EndPoint  isDelivered Customer
0     A           1         4            0       C1
1     A           1         4            0       C1
4     A           3         6            0       C1
5     A           3         6            1       C1
6     B           1         4            0       C2
7     B           1         4            0       C2
11    B           3         8            0       C2
12    B           3         8            1       C2

但第 4 行和第 11 行在 isDelivered 中没有值 1,因此它们不满足第二个条件。

我想要的结果是:

   Name  StartPoint  EndPoint  isDelivered Customer
0     A           1         4            0       C1 # Min value in StartPoint
1     A           1         4            0       C1 # Min value in StartPoint
5     A           3         6            1       C1 # Max value in EndPoint and 1 in isDelivered
6     B           1         4            0       C2 # Min value in StartPoint
7     B           1         4            0       C2 # Min value in StartPoint
12    B           3         8            1       C2 # Max value in EndPoint and 1 in isDelivered

有没有办法使用我当前的解决方案来实现这一点?

【问题讨论】:

【参考方案1】:

你在正确的轨道上,你只需要在最后一行代码中添加一个额外的条件:

df1 = df[(df.StartPoint==min_StartPoint)|((df.EndPoint==max_EndPoint) 
                                         & (df.isDelivered == 1))]
 
   Name  StartPoint  EndPoint  isDelivered Customer
0     A           1         4            0       C1
1     A           1         4            0       C1
5     A           3         6            1       C1
6     B           1         4            0       C2
7     B           1         4            0       C2
12    B           3         8            1       C2

【讨论】:

天啊,我意识到我使用的是逻辑“和”而不是按位“&”,这就是我没有得到结果的原因!我的一个愚蠢的错误。非常感谢您的回答!【参考方案2】:

您从未合并第二个条件的两个子句。使您的代码反映给定的措辞:保存的行必须符合以下两个条件之一:

df1 = df[(df.StartPoint == min_StartPoint) |
         ((df.EndPoint  == max_EndPoint) & df.isDelivered == 1)]

我很乐意向您展示实际输出,但您未能提供预期的输出,请参阅MRE - Minimal, Reproducible Example。

【讨论】:

非常感谢您的澄清!【参考方案3】:

您可以对每个组应用过滤器:

df.groupby(['Name'], group_keys=False).apply(
    lambda g:g[(g.StartPoint == g.StartPoint.min()) |
               ((g.EndPoint == g.EndPoint.max()) & (g.isDelivered == 1))])

输出:

    Name    StartPoint  EndPoint    isDelivered Customer
0   A       1           4           0           C1
1   A       1           4           0           C1
5   A       3           6           1           C1
6   B       1           4           0           C2
7   B       1           4           0           C2
12  B       3           8           1           C2

【讨论】:

感谢您的回答。我意识到我使用的是逻辑“and”而不是按位“&”,这就是我没有得到结果的原因。在发布问题之前我应该​​仔细检查一下。

以上是关于熊猫:分组并根据条件在每个组中删除行的主要内容,如果未能解决你的问题,请参考以下文章

相邻行熊猫的分组条件总和

在熊猫中按多个条件分组[重复]

在SQL中分组查询 Group by 的存在条件是啥

如何根据分组变量计算所有列的总和并删除 NA

根据 3 到 4 个条件对数据库表中的行进行计数和分组查询

熊猫:分组,过滤行,获取平均值