【问题标题】:Pandas reindex and interpolate time series efficiently (reindex drops data)Pandas 有效地重新索引和插入时间序列(重新索引丢弃数据)
【发布时间】:2018-10-08 11:31:59
【问题描述】:

假设我希望通过线性插值将时间序列重新索引为预定义索引,其中没有任何索引值在新旧索引之间共享。例如

# index is all precise timestamps e.g. 2018-10-08 05:23:07
series = pandas.Series(data,index) 

# I want rounded date-times
desired_index = pandas.date_range("2010-10-08",periods=10,freq="30min") 

Tutorials/API 建议这样做的方法是 reindex 然后使用 interpolate 填充 NaN 值。但是,由于新旧索引之间的日期时间没有重叠,因此 reindex 输出所有 NaN:

# The following outputs all NaN as no date times match old to new index
series.reindex(desired_index)

我不想在reindex 期间填充最接近的值,因为这会失去精度,所以我想出了以下内容;在插值之前将重新索引的系列与原始系列连接起来:

pandas.concat([series,series.reindex(desired_index)]).sort_index().interpolate(method="linear")

这似乎效率很低,将两个系列串联然后排序。有没有更好的办法?

【问题讨论】:

    标签: python pandas time-series


    【解决方案1】:

    我能看到的唯一(简单)方法是使用 resample 上采样到您的时间分辨率(比如 1 秒),然后重新索引。

    获取示例 DataFrame:

    import numpy as np
    import pandas as pd
    
    np.random.seed(2)
    
    df = (pd.DataFrame()
     .assign(SampleTime=pd.date_range(start='2018-10-01', end='2018-10-08', freq='30T')
                        + pd.to_timedelta(np.random.randint(-5, 5, size=337), unit='s'),
             Value=np.random.randn(337)
             )
     .set_index(['SampleTime'])
    )
    

    让我们看看数据是什么样的:

    df.head()
    
                            Value
    SampleTime
    2018-10-01 00:00:03     0.033171
    2018-10-01 00:30:03     0.481966
    2018-10-01 01:00:01     -0.495496
    

    获取所需的索引:

    desired_index = pd.date_range('2018-10-01', periods=10, freq='30T')
    

    现在,使用所需索引和现有索引的并集重新索引数据,根据时间进行插值,然后仅使用所需索引再次重新索引:

    (df
     .reindex(df.index.union(desired_index))
     .interpolate(method='time')
     .reindex(desired_index)
    )
    
                            Value
    2018-10-01 00:00:00     NaN
    2018-10-01 00:30:00     0.481218
    2018-10-01 01:00:00     -0.494952
    2018-10-01 01:30:00     -0.103270
    

    如您所见,第一个时间戳仍然存在问题,因为它超出了原始索引的范围;有很多方法可以解决这个问题(例如pad)。

    【讨论】:

    • resampleinterpolate 是否适合懒惰,或者他们会计算数千个我不需要的值?
    • 啊,是的,那是我忘记添加的警告。 resample 是惰性的,但 interpolate 不是,所以如果您有大量数据可能需要一段时间。
    • @SideshowBob 我已将答案更正为使用interpolate(method='time'),这要好得多。
    • 太好了,谢谢。我不知道index.union 是否总是排序或仅在必要时排序,所以如果不是,它仍然可能效率低下 - 但至少现在我觉得我正在使用我应该使用的熊猫,所以这是图书馆的错不是我的;)
    【解决方案2】:

    我的方法

        frequency = nyse_trading_dates.rename_axis([None]).index
        
        df = prices.rename_axis([None]).reindex(frequency)
    
        for d in prices.rename_axis([None]).index:
            df.loc[d] = prices.loc[d]
            
        df.interpolate(method='linear')
        
    

    方法二

        prices = data.loc[~data.index.duplicated(keep='last')]        
        #prices = data.reset_index()
    
        idx1 = prices.index  
        idx1 = pd.to_datetime(idx1, errors='coerce')
    
        merged = idx1.union(idx2)
        s = prices.reindex(merged)
        df = s.interpolate(method='linear').dropna(axis=0, how='any')
    
        data=df
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-05-16
      • 2018-11-06
      • 2021-12-09
      • 1970-01-01
      • 2021-07-26
      • 2018-11-26
      • 1970-01-01
      • 2019-02-05
      相关资源
      最近更新 更多