【问题标题】:Collapsing a Dataframe with Pandas to a single row per group使用 Pandas 将 Dataframe 折叠为每组一行
【发布时间】:2018-07-31 01:01:49
【问题描述】:

我有一个如下所示的数据框:

id A    B     date
a  1    NAN 2016-01-01
a  NAN  6   2016-01-02
a  7    NAN 2016-10-01
b  3    5   2016-12-01

我想按日期和 ID 折叠(每个组都放在一行中,使用组中最后一个日期的数据,并用组中的最新数据填充缺失的数据)。 groupby 大致如下所示:

df.groupby(['id', pd.Grouper(key='date', freq='30D')])

这将产生一个像这样的数据框:

id A    B     date
a  1    6   2016-01-02
a  7    NAN 2016-10-01
b  3    5   2016-12-01

一个非常简单的例子。我相信我的 groupby 会起作用,但我不确定如何将行组合成一行,并使用每列中的最新数据聚合数据,如有必要,转发填充数据(如果它们都是 NAN,只需使用一个 NAN)。

【问题讨论】:

    标签: python pandas pandas-groupby


    【解决方案1】:
    df.groupby(['id', pd.Grouper(key='date', freq='30D')]).apply(lambda g: g[["A", "B"]].ffill().iloc[-1])
    

    结果:

                   A    B
    id date
    a  2016-01-01  1  6.0
       2016-09-27  7  NaN
    b  2016-11-26  3  5.0
    

    编辑:为了解决您的评论,如果您想避免使用apply,您也可以使用两个groupbys:

    groupers = ['id', pd.Grouper(key='date', freq='30D')]
    df.groupby(groupers).ffill().groupby(groupers).last()
    

    结果:

                   A    B
    id date
    a  2016-01-01  1    6
       2016-09-27  7  NaN
    b  2016-11-26  3    5
    

    看起来性能类似于apply

    In [1]: groupers = ['id', pd.Grouper(key='date', freq='30D')]
    
    In [2]: %%timeit
        ...: df.groupby(groupers).ffill().groupby(groupers).last()
        ...:
    100 loops, best of 3: 9.79 ms per loop
    
    In [3]: %%timeit
        ...: df.groupby(groupers).apply(lambda g: g[["A", "B"]].ffill().iloc[-1])
        ...:
    100 loops, best of 3: 10.5 ms per loop
    

    【讨论】:

    • 确实有效!惊人的。总的来说,我认为apply 的效率可能非常低,仅在不得已的情况下才被鼓励。有没有更好的方法来做到这一点,或者由于对数据进行必要的修改,这真的是一个很好的申请案例吗?
    • 我在一些具有数百万行的数据帧上进行了测试,没有应用的方法要快几个数量级!
    猜你喜欢
    • 2020-03-20
    • 2019-08-07
    • 1970-01-01
    • 1970-01-01
    • 2022-01-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-01-15
    相关资源
    最近更新 更多