针对 float64 与 object 和 int64 列对具有不同条件的时间序列进行上采样
Posted
技术标签:
【中文标题】针对 float64 与 object 和 int64 列对具有不同条件的时间序列进行上采样【英文标题】:Upsampling a time-series with different conditions for float64 vs object and int64 columns 【发布时间】:2017-01-03 17:20:58 【问题描述】:我有一个类似这样的df
:
print(df)
A B C
DATE_TIME
2016-10-08 13:57:00 in 5.61 0
2016-10-08 14:02:00 in 8.05 0
2016-10-08 14:07:00 out 7.92 0
2016-10-08 14:12:00 in 7.98 1
2016-10-08 14:17:00 out 8.18 0
2016-10-08 14:22:00 out 7.59 0
print (df.dtypes)
A object
B float64
C int64
dtype: object
我想将此df
重新采样为1S 频率,以便我可以将它与另一个df
连接起来。
我无法解决的问题是,对于object
和int64
类型的列,我希望为新创建的时间行重复相同的值,这可以通过这个函数来完成:
df=df.resample('S', fill_method='pad')
而对于 float64
列,我正在寻找这个:
df=df.interpolate()
我考虑过应用 IF 语句,但我也认为我首先必须在插值步骤之前执行重新采样步骤。当我仅通过df=df.resample('S')
重新采样时,我可以在之后进行插值,这适用于float64
列,但不适用于object
和Int64
列。
有人可以帮我吗?谢谢。
【问题讨论】:
【参考方案1】:这是一个使用reindex
的方法:
index = pd.date_range(df.index[0], df.index[-1], freq="s")
df2 = df.reindex(index)
for col, s in df2.iteritems():
if s.dtype == float:
s.interpolate(inplace=True)
else:
s.ffill(inplace=True)
【讨论】:
【参考方案2】:更新:我认为您仍然可以使用矢量化方法(而不是循环遍历您的数据框),即使您有多个 float
列 - 它应该更快:
假设您有以下 DF(列:['B','D']
属于 float
dtype):
In [18]: df
Out[18]:
A B C D
DATE_TIME
2016-10-08 13:57:00 in 5.61 0 6.2271
2016-10-08 14:02:00 in 8.05 0 8.9355
2016-10-08 14:07:00 out 7.92 0 8.7912
2016-10-08 14:12:00 in 7.98 1 8.8578
2016-10-08 14:17:00 out 8.18 0 9.0798
2016-10-08 14:22:00 out 7.59 0 8.4249
In [19]: df.dtypes
Out[19]:
A object
B float64
C int64
D float64
dtype: object
您可以执行以下操作(适用于 pandas 版本:0.18.0+):
rsmpl = df.resample('S')
pd.concat([rsmpl.pad()[df.select_dtypes(exclude=['float']).columns],
rsmpl.interpolate()[df.select_dtypes(include=['float']).columns]],
axis=1)
例子:
In [23]: pd.concat([rsmpl.pad()[df.select_dtypes(exclude=['float']).columns],
....: rsmpl.interpolate()[df.select_dtypes(include=['float']).columns]],
....: axis=1).head()
Out[23]:
A C B D
DATE_TIME
2016-10-08 13:57:00 in 0 5.610000 6.227100
2016-10-08 13:57:01 in 0 5.618133 6.236128
2016-10-08 13:57:02 in 0 5.626267 6.245156
2016-10-08 13:57:03 in 0 5.634400 6.254184
2016-10-08 13:57:04 in 0 5.642533 6.263212
旧答案:
您可以先resample('S')
和pad()
然后用df.resample('S').interpolate().B
重新分配float64
列B
:
In [96]: df.resample('S').pad().assign(B=df.resample('S').interpolate().B)
Out[96]:
A B C
DATE_TIME
2016-10-08 13:57:00 in 5.610000 0
2016-10-08 13:57:01 in 5.618133 0
2016-10-08 13:57:02 in 5.626267 0
2016-10-08 13:57:03 in 5.634400 0
2016-10-08 13:57:04 in 5.642533 0
2016-10-08 13:57:05 in 5.650667 0
2016-10-08 13:57:06 in 5.658800 0
2016-10-08 13:57:07 in 5.666933 0
2016-10-08 13:57:08 in 5.675067 0
2016-10-08 13:57:09 in 5.683200 0
2016-10-08 13:57:10 in 5.691333 0
2016-10-08 13:57:11 in 5.699467 0
2016-10-08 13:57:12 in 5.707600 0
2016-10-08 13:57:13 in 5.715733 0
2016-10-08 13:57:14 in 5.723867 0
2016-10-08 13:57:15 in 5.732000 0
2016-10-08 13:57:16 in 5.740133 0
2016-10-08 13:57:17 in 5.748267 0
2016-10-08 13:57:18 in 5.756400 0
2016-10-08 13:57:19 in 5.764533 0
2016-10-08 13:57:20 in 5.772667 0
2016-10-08 13:57:21 in 5.780800 0
2016-10-08 13:57:22 in 5.788933 0
2016-10-08 13:57:23 in 5.797067 0
2016-10-08 13:57:24 in 5.805200 0
2016-10-08 13:57:25 in 5.813333 0
2016-10-08 13:57:26 in 5.821467 0
2016-10-08 13:57:27 in 5.829600 0
... ... ... ..
或者更快一点的版本(一个 resample()
调用而不是两个):
rsmpl = df.resample('S')
rsmpl.pad().assign(B=rsmpl.interpolate().B)
【讨论】:
我选择了第一个答案,因为我可以更通用地将其应用于我的df
,它有更多的列,而不必单独指定它们。注意:我必须将代码调整为df.resample('S', fill_method='pad').assign(B=df.resample('S').interpolate().B)
,否则我会收到错误消息`AttributeError: 'DataFrame' object has no attribute 'pad'`。我不知道如何修改更快的版本以不收到该错误消息。非常感谢你们!
@vera,从 pandas 0.18.0 开始,重采样 API has been changed - 很可能您使用的是旧版 pandas。
@vera,我已经更新了我的答案 - 现在它将处理多个 float
列,并且仍将使用矢量化方法
酷,谢谢!该解决方案看起来更简单,我真的很想测试它。我仍在阅读如何在 Spyder(Python 3.5)上更新我的 pandas 版本(0.17.0)。我尝试使用`conda update pandas` ...它不起作用,当我输入help(conda)
时,它显示NameError: name 'conda' is not defined
。我觉得我在这里缺少一些基础知识.....以上是关于针对 float64 与 object 和 int64 列对具有不同条件的时间序列进行上采样的主要内容,如果未能解决你的问题,请参考以下文章