Pandas:使用日期时间索引进行分组前向填充

Posted

技术标签:

【中文标题】Pandas:使用日期时间索引进行分组前向填充【英文标题】:Pandas: groupby forward fill with datetime index 【发布时间】:2016-11-30 12:53:18 【问题描述】:

我有一个包含两列的数据集:公司和价值。 它有一个日期时间索引,其中包含重复项(同一天,不同的公司有不同的值)。这些值缺少数据,所以我想用同一家公司的前一个数据点转发填充缺失的数据。

但是,我似乎找不到一个好方法来做到这一点,而不会遇到奇怪的 groupby 错误,这表明我做错了什么。

玩具数据:

a = pd.DataFrame('a': [1, 2, None], 'b': [12,None,14])
a.index = pd.DatetimeIndex(['2010', '2011', '2012'])  
a = a.unstack() 
a = a.reset_index().set_index('level_1') 
a.columns = ['company', 'value'] 
a.sort_index(inplace=True)

尝试的解决方案(无效:ValueError: cannot reindex from a duplicate axis):

a.groupby('company').ffill() 
a.groupby('company')['value'].ffill() 
a.groupby('company').fillna(method='ffill')

Hacky 解决方案(提供了预期的结果,但显然只是一个丑陋的解决方法):

a['value'] = a.reset_index().groupby(
    'company').fillna(method='ffill')['value'].values

这可能有一种简单而优雅的方法,这在 Pandas 中是如何执行的?

【问题讨论】:

【参考方案1】:

我喜欢使用堆叠和拆解。在这种情况下,它要求我在索引后面附加'company'

a.set_index('company', append=True).unstack().ffill() \
                                   .stack().reset_index('company')


时间

结论@Psidom 的解决方案在这两种情况下效果最佳。

玩具数据

更大的玩具

np.random.seed([3,1415])
n = 10000
a = pd.DataFrame(np.random.randn(n, 10),
                 pd.date_range('2014-01-01', periods=n, freq='H', name='Time'),
                 pd.Index(list('abcdefghij'), name='company'))

a *= np.random.choice((1, np.nan), (n, 10), p=(.6, .4))

a = a.stack(dropna=False).rename('value').reset_index('company')

【讨论】:

【参考方案2】:

您可以将'company' 添加到索引中,使其唯一,并通过groupby 做一个简单的ffill

a = a.set_index('company', append=True)
a = a.groupby(level=1).ffill()

如有必要,您可以在此处使用reset_index 将索引恢复为刚刚的日期。我建议将 'company' 保留为索引的一部分(或者只是将其添加到索引中),这样您的索引将保持唯一:

a = a.reset_index(level=1)

【讨论】:

【参考方案3】:

一种方法是使用transform 函数在分组后填充value 列:

import pandas as pd
a['value'] = a.groupby('company')['value'].transform(lambda v: v.ffill())

a
#          company  value
#level_1        
#2010-01-01      a    1.0
#2010-01-01      b   12.0
#2011-01-01      a    2.0
#2011-01-01      b   12.0
#2012-01-01      a    2.0
#2012-01-01      b   14.0

为了比较,原始数据框如下所示:

#            company    value
#level_1        
#2010-01-01        a      1.0
#2010-01-01        b     12.0
#2011-01-01        a      2.0
#2011-01-01        b      NaN
#2012-01-01        a      NaN
#2012-01-01        b     14.0

【讨论】:

我发现a['value'] = a.groupby('company')['value'].transform(lambda v: v.ffill())a['value'] = a.groupby('company')['value'].ffill() 之间的结果没有差异

以上是关于Pandas:使用日期时间索引进行分组前向填充的主要内容,如果未能解决你的问题,请参考以下文章

Python Pandas 索引排序/分组/日期时间

分组日期滚动中最新非空值的 Pandas 日期索引

Pandas Python - 计数和分组日期时间索引

Python Pandas:按日期分组,并按时间戳访问每个组

pandas DataFrame中按日期(在索引中)的加权平均分组(每列不同的操作)

使用空值对 pandas 日期时间进行分组