【问题标题】:Delete all rows before the first appearance of a condition in a pandas data frame删除熊猫数据框中第一次出现条件之前的所有行
【发布时间】:2023-03-23 06:21:01
【问题描述】:

我有以下数据框:

df = pd.DataFrame({"Person":[1,1,2,2,3,3,3,3], "Bank":["B1","B2","B9","B2","B6","B1","B1","B5",]})

   Person Bank
0       1   B1
1       1   B2
2       2   B9
3       2   B2
4       3   B6
5       3   B1
6       3   B1
7       3   B5

我想删除每个人在第一次出现B1 之前的所有行。也就是说,我想保留Bank == B1 和以下的行。

这是我想要的:

   Person Bank
0       1   B1
1       1   B2
5       3   B1
6       3   B1
7       3   B5

如果B1 从未发生过,则清除属于该人的所有行。如果B1 首次出现之前有行,我想删除它们。

【问题讨论】:

    标签: python pandas


    【解决方案1】:

    使用mask + ffill

    m = df['Bank'].where(df['Bank'] == 'B1').groupby(df['Person']).ffill()
    
    df[m.notnull()]
    

       Person Bank
    0       1   B1
    1       1   B2
    5       3   B1
    6       3   B1
    7       3   B5
    

    这通过使组中第一次出现之后的所有内容都成为非空值来工作。这分两步完成:

    1) 屏蔽所有无效有效的内容。

    df['Bank'].where(df['Bank'] == 'B1')
    

    0     B1
    1    NaN
    2    NaN
    3    NaN
    4    NaN
    5     B1
    6     B1
    7    NaN
    Name: Bank, dtype: object
    

    2) 每组向前填充。这是答案的真正关键。这意味着B1 中第一次出现之后的所有值都将填充有效字符串(每组),因此notnull 不会删除它们

    >>> m
    0     B1
    1     B1
    2    NaN
    3    NaN
    4    NaN
    5     B1
    6     B1
    7     B1
    Name: Bank, dtype: object
    

    一旦我们有了有效的掩码,过滤掩码不为空的 DataFrame 就很简单了。

    【讨论】:

    • 您能解释一下为什么会这样吗?我可以看到 df.Bank.where(df.bank == "B1") 在符合条件的行中返回人员 ID。按人和ffill() 分组有什么作用?
    • @ArturoSbr 我更新了显示中间结果的答案
    • 太棒了。谢谢! ffill() 是否代表“前向填充”?
    • 是的,确实如此。 Other types can be found here
    【解决方案2】:

    使用cumsum 及其布尔对应对象 (astype(bool))

    df[df.groupby('Person').Bank.transform(lambda s: s.eq('B1').cumsum().astype(bool))]
    

       Person Bank
    0       1   B1
    1       1   B2
    5       3   B1
    6       3   B1
    7       3   B5
    

    【讨论】:

      【解决方案3】:

      您可以通过transform查看

      s=(df['Bank']=='B1').groupby(df['Person'])
      
      df[(df.index>=(s.transform('idxmax')))&s.transform('any')]
      Out[305]: 
         Person Bank
      0       1   B1
      1       1   B2
      5       3   B1
      6       3   B1
      7       3   B5
      

      【讨论】:

      • 我想从Person 3 中排除B6 并保留B5。
      • @ArturoSbr 在您的问题中,您打印的 DataFrame 和代码 DataFrame 不匹配。后者缺少一行
      猜你喜欢
      • 1970-01-01
      • 2013-10-04
      • 1970-01-01
      • 1970-01-01
      • 2013-04-30
      • 1970-01-01
      • 1970-01-01
      • 2019-02-26
      • 2017-10-04
      相关资源
      最近更新 更多