首页 > 解决方案 > 使用 Pandas 将 Dataframe 折叠为每组一行

问题描述

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

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,只需使用一个南)。

标签: pythonpandaspandas-groupby

解决方案


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

推荐阅读