【问题标题】:Upsampling a time-series with different conditions for float64 vs object and int64 columns针对 float64 与 object 和 int64 列对具有不同条件的时间序列进行上采样
【发布时间】: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 连接起来。 我无法解决的问题是,对于objectint64 类型的列,我希望为新创建的时间行重复相同的值,这可以通过这个函数来完成:

df=df.resample('S', fill_method='pad')

而对于 float64 列,我正在寻找这个:

df=df.interpolate()

我考虑过应用 IF 语句,但我也认为我首先必须在插值步骤之前执行重新采样步骤。当我仅通过df=df.resample('S') 重新采样时,我可以在之后进行插值,这适用于float64 列,但不适用于objectInt64 列。 有人可以帮我吗?谢谢。

【问题讨论】:

    标签: pandas time-series interpolation resampling


    【解决方案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 重新分配float64B

      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。我觉得我在这里缺少一些基础知识.....
      猜你喜欢
      • 2018-06-17
      • 2017-11-18
      • 2019-10-22
      • 2017-01-06
      • 2021-10-01
      • 2019-01-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多