【问题标题】:How to use double groupby in Pandas and filter based on if condition?如何在 Pandas 中使用 double groupby 并根据 if 条件进行过滤?
【发布时间】:2021-02-04 15:08:45
【问题描述】:

我有一个名为 df 的数据框,在 Pandas 中看起来像这样:

**id        amt          date       seq**
SB      450,000,000  2020-05-11  1
OM      430,000,000  2020-05-11  1
SB      450,000,000  2020-05-12  1
OM      450,000,000  2020-05-12  1
OM      130,000,000  2020-05-12  2  

我需要在 amt 中找到每天每个 ID 的值。问题是,有时会有多个周期,如“seq”所示。

如果任何一天有 2 个周期(又名 seq=2),我需要在 seq=2 时取该 id 当天的值,并删除同一天和 id 的 seq=1 的任何值.有些日子,任何一个 id 都只有 1 个周期,在那些日子里,我可以坚持使用 seq=1 的值。

我的目标是 Pandas groupby day 然后再 groupby id,然后应用 if 语句判断 seq 列是否包含该 id 和那一天的 2,然后过滤该 groupby 对象以仅包含 seq=2 的行那天和身份证。最终结果将是一个数据框,其中仅包含 seq=2 的行(当有多个周期和seq=12)和 seq=1 的行(对于只有一个周期和 seq 的天) =1 对于所有 ID。

到目前为止我已经尝试过:

`for day in df.groupby(df['date']):
    for id in day[1].groupby(['id']):
        if 2 in id[1]['seq']:
            id[1]=id[1].apply(lambda g: g[g['seq']==2])`

这给了我: KeyError:'seq'

我也试过了:

`for day in df.groupby(df['date']):
    for id in day[1].groupby(['id']):
        id=list(id)
        if 2 in id[1]['seq']:
            id[1]=id[1][id[1]['seq']==2]`

运行良好,但实际上并没有改变或对 df 做任何事情(保留相同数量的行)。

谁能帮我解决这个问题?

提前谢谢你!

【问题讨论】:

    标签: pandas dataframe filter pandas-groupby


    【解决方案1】:

    如果您按日期 + id 分组,则可以执行此操作,然后获取 seq 为这些分组的最大值的行的索引。获得这些索引后,您可以切回原始数据帧以获得所需的子集:

    max_seq_indices = df.groupby(["date", "**id"])["seq**"].idxmax()
    
    print(max_seq_indices)
    date        **id
    2020-05-11  OM      1
                SB      0
    2020-05-12  OM      4
                SB      2
    Name: seq**, dtype: int64
    

    查看这个 Series 的值,您可以看到我们在第 1 行有一个最大的 ["2020-05-11", "OM"] seq。同样,对于 ["2020- 05-11", "SB"] 在第 0 行。依此类推。如果我们使用它来切回到我们的原始数据框,我们最终会得到您在问题中描述的子集:

    new_df = df.loc[max_seq_indices]
    
    print(new_df)
      **id          amt        date  seq**
    1   OM  430,000,000  2020-05-11      1
    0   SB  450,000,000  2020-05-11      1
    4   OM  130,000,000  2020-05-12      2
    2   SB  450,000,000  2020-05-12      1
    

    如果您的 seq 大于 2,但只需要 seq 为 2 的行,这种方法会遇到问题。但是,如果是这种情况,请发表评论,我可以用更强大的更新我的答案(但可能更复杂)解决方案

    【讨论】:

      【解决方案2】:

      您还可以使用已排序的数据框,例如:

      df.sort_values(['date', '**id', 'seq**'], inplace=True)
      

      然后你可以使用 groupby 只取每个组的最后一个

      df.reset_index(drop=True).groupby(['date', '**id'])['amt'].agg('last')
      

      【讨论】:

        猜你喜欢
        • 2023-04-02
        • 2022-01-17
        • 1970-01-01
        • 2021-03-05
        • 2018-07-22
        • 2022-01-01
        • 1970-01-01
        • 2022-08-08
        • 2020-05-25
        相关资源
        最近更新 更多