【问题标题】:How to find periodicity of time series spanning micro time units?如何找到跨越微时间单位的时间序列的周期性?
【发布时间】:2019-05-02 05:52:03
【问题描述】:

我有一个时间序列,其中时间单位是毫秒,而序列 大约有3000个条目。我试图找出季节性 这个系列的,例如检测数据中的任何周期性故障。数据是 表示为 pandas 数据框。

我尝试使用 statsmodel 中的seasonal_decompose() 方法,如下所示:

import pandas as pd
data = pd.read_csv('Sample_data.csv',index_col=0)
data.index = pd.to_datetime(data.index)
print(data.head())
##                              Sample_values
## Dates    
## 1970-01-01 05:30:00.000000   0.466812
## 1970-01-01 05:30:00.016667   0.218692
## 1970-01-01 05:30:00.033333   0.938067
## 1970-01-01 05:30:00.050000   0.480025
## 1970-01-01 05:30:00.066667   0.915175
print(type(data))
##  <class 'pandas.core.frame.DataFrame'>
from statsmodels.tsa.seasonal import seasonal_decompose
result = seasonal_decompose(data, model='additive')
fig = result.plot()

但是会导致如下错误:

ValueError: You must specify a freq or x must be a pandas object with a timeseries index with a freq not set to None

但是,如果我对 x 轴单位以月为单位的数据集使用相同的代码(例如,从 https://www.analyticsvidhya.com/wp-content/uploads/2016/02/AirPassengers.csv 下载),那么我不会收到任何错误,并且我会按预期从seasonal_decompose() 获得 4 个图。

那么我如何检测我的数据类型的季节性模式,它只跨越 几个小时?

【问题讨论】:

    标签: python pandas statsmodels


    【解决方案1】:

    您需要为日期时间索引定义freq

    使用以下内容:

                                sample_values
    1970-01-01 05:30:00.000000       0.466812
    1970-01-01 05:30:00.016667       0.218692
    1970-01-01 05:30:00.033333       0.938067
    1970-01-01 05:30:00.050000       0.480025
    1970-01-01 05:30:00.066667       0.915175
    

    目前频率为None

    In [1]: print df.index
    DatetimeIndex([       '1970-01-01 05:30:00', '1970-01-01 05:30:00.016667',
                   '1970-01-01 05:30:00.033333', '1970-01-01 05:30:00.050000',
                   '1970-01-01 05:30:00.066667'],
                  dtype='datetime64[ns]', freq=None)
    

    而 Pandas infer_freq 函数无法检测到它:

    In [2]: print pd.infer_freq(df.index)
    None
    

    如果您知道数据的频率应该是多少,您可以重新索引到该频率。但是,这对您的索引很困难,因为时间戳中的重复小数需要四舍五入到某个定义的间隔。这接近了:

    In [3]: df_freq = df.resample('.000001S').ffill().reindex(pd.date_range(df.index[0],df.index[-1],freq='0.016667S'))
    
    In [4]: print df_freq
                                sample_values
    1970-01-01 05:30:00.000000       0.466812
    1970-01-01 05:30:00.016667       0.218692
    1970-01-01 05:30:00.033334       0.938067
    1970-01-01 05:30:00.050001       0.480025
    
    In [5]: print df_freq.index
    DatetimeIndex([       '1970-01-01 05:30:00', '1970-01-01 05:30:00.016667',
                   '1970-01-01 05:30:00.033334', '1970-01-01 05:30:00.050001'],
                  dtype='datetime64[ns]', freq='16667U')
    

    现在您已经定义了freq。在你的完整数据集上试试这个,看看seasonal_decompose() 是否会运行。但是,时间戳可能会在很长一段时间后变得不准确。

    你也可以试试这样的:

    In [6]: df_freq = df.resample('.000001S').interpolate().resample('.005S').first()
    
    In [7]: print df_freq
                             sample_values
    1970-01-01 05:30:00.000       0.466812
    1970-01-01 05:30:00.005       0.392377
    1970-01-01 05:30:00.010       0.317943
    1970-01-01 05:30:00.015       0.243508
    1970-01-01 05:30:00.020       0.362558
    1970-01-01 05:30:00.025       0.578380
    1970-01-01 05:30:00.030       0.794201
    1970-01-01 05:30:00.035       0.892255
    1970-01-01 05:30:00.040       0.754845
    1970-01-01 05:30:00.045       0.617435
    1970-01-01 05:30:00.050       0.480025
    1970-01-01 05:30:00.055       0.610567
    1970-01-01 05:30:00.060       0.741110
    1970-01-01 05:30:00.065       0.871652
    

    这有freq='5L',并使用线性插值来近似原始数据与常规频率索引的趋势。如果需要,您可以对第二个下采样频率使用 .005S 进行试验,以获得更高或更低的频率。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-03-27
      • 1970-01-01
      • 2021-07-23
      • 2016-02-14
      • 1970-01-01
      • 1970-01-01
      • 2016-11-08
      相关资源
      最近更新 更多