sap*_*ico 3 python datetime group-by missing-data pandas
我有一个包含两列的数据集:company和value.
它有一个日期时间索引,其中包含重复项(在同一天,不同的公司具有不同的值).这些值缺少数据,因此我想使用同一公司的前一个数据点转发缺少的数据.
但是,我似乎无法找到一个很好的方法来做到这一点,而不会遇到奇怪的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)
Run Code Online (Sandbox Code Playgroud)
尝试过的解决方案(不起作用:) ValueError: cannot reindex from a duplicate axis:
a.groupby('company').ffill()
a.groupby('company')['value'].ffill()
a.groupby('company').fillna(method='ffill')
Run Code Online (Sandbox Code Playgroud)
Hacky解决方案(提供所需的结果,但显然只是一个丑陋的解决方法):
a['value'] = a.reset_index().groupby(
'company').fillna(method='ffill')['value'].values
Run Code Online (Sandbox Code Playgroud)
可能有一种简单而优雅的方式来做到这一点,这是如何在熊猫中进行的?
一种方法是使用该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
Run Code Online (Sandbox Code Playgroud)
作为比较,原始数据帧如下所示:
# 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
Run Code Online (Sandbox Code Playgroud)
您可以添加'company'到索引中,使其成为独特的,并做了简单的ffill通过groupby:
a = a.set_index('company', append=True)
a = a.groupby(level=1).ffill()
Run Code Online (Sandbox Code Playgroud)
从这里reset_index开始,如有必要,您可以使用将索引恢复为正好日期.我建议保留'company'作为索引的一部分(或者只是将其添加到索引中),因此您的索引仍然是唯一的:
a = a.reset_index(level=1)
Run Code Online (Sandbox Code Playgroud)
我喜欢使用堆叠和拆垛。在这种情况下,它要求我在索引后附加'company'.
a.set_index('company', append=True).unstack().ffill() \
.stack().reset_index('company')
Run Code Online (Sandbox Code Playgroud)
结论@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')
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
6356 次 |
| 最近记录: |