Python:回顾n天滚动标准偏差

时间:2015-03-17 20:11:08

标签: python pandas

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

数据框如下所示:

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'的格式是日期戳)

我想计算标准偏差的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-01-21 15:08结束,2010-01-22 05:10:00开始。 因此,使用常量设置窗口大小可能无法解决此问题。 有什么建议?非常感谢

1 个答案:

答案 0 :(得分:7)

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

您可以在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

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

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

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


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

如果你有足够的记忆力,我认为应对这种情况的最简单方法 是使用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天窗口的正确子系列。虽然这是可能的,但事实是这样的 你必须为时间序列的每一行计算这一点 方法很慢。因此,我认为更快的方法是扩大时间 系列。