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:按日期分组,并按时间戳访问每个组