【问题标题】:Select all the groups that meet condition at least once选择至少一次满足条件的所有组
【发布时间】:2019-12-24 05:18:00
【问题描述】:

我想保留至少一次满足条件的组的所有行。换句话说,我想将不满足条件的组至少删除一次。

我已经四处寻找了几个小时,但找不到解决方案。 This was the closest I got 但我无法实现答案。

我有以下数据框:

test = pd.DataFrame({"Gr":[1,1,2,2],"Bk":[9,1,8,5]})
print(test)

   Gr  Bk
0   1   9
1   1   1
2   2   8
3   2   5

我想按test["Gr"] 分组并选择test["Bk"] == 9 至少一次的所有组以达到此目的:

# Drop Gr 2 because they didn't meet Bk == 1 in any of its rows.
   Gr  Bk
0   1   9
1   1   1

我原以为这可以通过组合 groupby().any() 轻松实现,而无需 lambda 函数。

我试过这个:

test.groupby("Gr").filter(lambda x: (x.Bk == 9).all())

【问题讨论】:

    标签: python pandas filter any


    【解决方案1】:

    使用GroupBy.transformeq.any 在每个组内检查any 的值是否等于(eq)到9

    mask = test.groupby('Gr')['Bk'].transform(lambda x: x.eq(9).any())
    test[mask]
    

    输出

       Gr  Bk
    0   1   9
    1   1   1
    

    【讨论】:

    • 这很好用,但为什么需要 lambda 部分?
    • 因为我们使用transform 来获得TrueFalse 的等长数组,它指示是否应在我们的结果中返回该行。 Lambda 是必要的,因为我们应用了多个 pandas 方法(eqany)。
    • 谢谢伙计。最后一个问题:lambda 函数是逐行执行的吗?
    【解决方案2】:

    你可以这样做:

    test =test[test['Gr'].apply(lambda x: x in [key for key in test['Gr'][test['Bk'].eq(9)]])]
    test
    

    输出:

        Gr  Bk
    0   1   9
    1   1   1
    

    【讨论】:

      【解决方案3】:

      没有 groupby 也有可能。只需检查所有条目是否等于 9,获取此条目的组并为提取的组分割整个数据帧。

      test[test.Gr.isin(test[test['Bk'].eq(9)].Gr)]
      

      结果

          Gr  Bk
      0   1   9
      1   1   1
      

      【讨论】:

        【解决方案4】:

        通俗易懂filter

        test.groupby('Gr').filter(lambda x : x['Bk'].eq(9).any())
           Gr  Bk
        0   1   9
        1   1   1
        

        【讨论】:

          【解决方案5】:

          假设每组 Gr 中只有一个 Bk=9 。这是使用merge 的一种疯狂且过度杀伤力的方式:D

          test.merge(test.loc[test.Bk.eq(9),'Gr'], on='Gr')
          
          Out[227]:
             Gr  Bk
          0  1   9
          1  1   1
          

          注意:它仍然适用于每个组的多个 9。它只需要drop_duplicates,但我认为在这一点上它变得太复杂了,不再有趣了

          【讨论】:

            【解决方案6】:

            这里的方法很简单..

            检查 test['Bk'] 等于 9 的位置,并获取 test['Gr'] 中的相应值,然后将 df 减少到仅出现这些 test['Gr'] 值的行

            test[test['Gr'].isin(test[test['Bk']==9]['Gr'])]
            

            结果:

               Gr  Bk
            0   1   9
            1   1   1
            

            【讨论】:

              猜你喜欢
              • 2021-11-04
              • 1970-01-01
              • 1970-01-01
              • 2014-12-02
              • 2022-09-28
              • 1970-01-01
              • 2012-01-07
              • 2022-06-13
              • 1970-01-01
              相关资源
              最近更新 更多