【问题标题】:Python: look back n days rolling standard deviationPython:回顾n天滚动标准差
【发布时间】:2015-03-17 20:11:07
【问题描述】:

我有一个关于处理滚动标准差的问题:

数据框如下所示:

2010-01-20 05:00:00   -0.011
2010-01-20 05:02:00   -0.032
2010-01-20 05:02:00   -0.037
2010-01-20 05:04:00    0.001
2010-01-20 05:06:00    0.023
2010-01-20 05:06:00    0.011
2010-01-20 05:08:00    0.049
2010-01-20 05:10:00    0.102
....
2010-05-20 17:00:00    0.022

这是从早上 5 点到下午 5 点的 2 分钟数据 (索引'yyyy-mm-dd hh:mm:ss'的格式为datestamp)

我想计算标准差的 8 天回顾。我的直觉是将数据框拆分为每日数据集,然后计算滚动标准差,但我不知道如何处理这些索引,我想我的方法可能需要大量时间来计算。非常感谢您的帮助!

最后,我想要这样的结果:

2010-01-20   0.0
2010-01-21   0.0
2010-01-22   0.0
....
2010-01-26   0.0
2010-01-27   0.12
2010-01-28   0.02
2010-01-29   0.07
...
2010-05-20   0.10

感谢您的帮助。 @unutbu

刚刚在数据中发现了问题: 数据框不完全包括整个 2 分钟数据。 例如:

2010-01-21 15:08:00    0.044
2010-01-22 05:10:00    0.102

数据于 2010 年 1 月 21 日 15:08 结束,2010 年 1 月 22 日 05:10:00 开始。 因此使用常量设置窗口大小可能无法解决此问题。 有什么建议么?非常感谢

【问题讨论】:

    标签: python pandas


    【解决方案1】:

    如果时间序列具有恒定频率:

    您可以计算 8 天内 2 秒内插的次数:

    window_size = pd.Timedelta('8D')/pd.Timedelta('2min')
    

    然后将pd.rolling_stdwindow=window_size 一起使用:

    import pandas as pd
    import numpy as np
    np.random.seed(1)
    
    index = pd.date_range(start='2010-01-20 5:00', end='2010-05-20 17:00', freq='2T')
    N = len(index)
    df = pd.DataFrame({'val': np.random.random(N)}, index=index)
    # the number of 2 second intervals in 8 days
    window_size = pd.Timedelta('8D')/pd.Timedelta('2min')    # 5760.0
    
    df['std'] = pd.rolling_std(df['val'], window=window_size)
    print(df.tail())
    

    产量

                              val       std
    2010-05-20 16:52:00  0.768918  0.291137
    2010-05-20 16:54:00  0.486348  0.291098
    2010-05-20 16:56:00  0.679610  0.291099
    2010-05-20 16:58:00  0.951798  0.291114
    2010-05-20 17:00:00  0.059935  0.291109
    

    要重新采样这个时间序列以便每天获得一个值,您可以使用resample method 并通过取平均值来聚合这些值:

    df['std'].resample('D', how='mean')
    

    产量

    ...
    2010-05-16    0.289019
    2010-05-17    0.289988
    2010-05-18    0.289713
    2010-05-19    0.289269
    2010-05-20    0.288890
    Freq: D, Name: std, Length: 121
    

    在上面,我们计算了滚动标准偏差,然后重新采样到某个时间 每日频率的系列。

    如果我们要将原始数据重新采样为每日频率首先,然后 计算滚动标准偏差,然后通常结果将是 不同。

    另请注意,您的数据看起来在每个数据中都有相当多的变化 天,因此通过取平均值重新采样可能(错误地?)隐藏这种变化。 所以最好先计算标准。


    如果时间序列没有恒定频率:

    如果你有足够的内存,我认为处理这种情况最简单的方法 是使用asfreq 将时间序列扩展为具有常数的时间序列 频率。

    import pandas as pd
    import numpy as np
    np.random.seed(1)
    
    # make an example df
    index = pd.date_range(start='2010-01-20 5:00', end='2010-05-20 17:00', freq='2T')
    N = len(index)
    df = pd.DataFrame({'val': np.random.random(N)}, index=index)
    mask = np.random.randint(2, size=N).astype(bool)
    df = df.loc[mask]
    
    # expand the time series, filling in missing values with NaN
    df = df.asfreq('2T', method=None)
    
    # now we can use the constant-frequency solution
    window_size = pd.Timedelta('8D')/pd.Timedelta('2min')    
    df['std'] = pd.rolling_std(df['val'], window=window_size, min_periods=1)
    
    result = df['std'].resample('D', how='mean')
    print(result.head())
    

    产量

    2010-01-20    0.301834
    2010-01-21    0.292505
    2010-01-22    0.293897
    2010-01-23    0.291018
    2010-01-24    0.290444
    Freq: D, Name: std, dtype: float64
    

    扩展时间序列的替代方法是编写代码来计算 每个 8 天窗口的正确子系列。虽然这是可能的,但事实上 你必须为时间序列的每一行计算这个才能做到这一点 方法很慢。因此,我认为更快的方法是扩大时间 系列。

    【讨论】:

    • 感谢 cmets。我想我明白了你的想法。
    • 嗨,unutbu,我发现数据不包括整个 2 分钟数据集。我应该谁来设置动态窗口大小,或者我应该改变另一种方式来计算这个滚动标准偏差(我已经更新了我的问题)你对新问题有什么建议吗?谢谢。
    猜你喜欢
    • 1970-01-01
    • 2014-05-09
    • 2017-03-04
    • 2017-04-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多