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

Jul*_*lia 2 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
Run Code Online (Sandbox Code Playgroud)

这是从早上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
Run Code Online (Sandbox Code Playgroud)

谢谢您的帮助.@unutbu

刚发现数据中的问题:数据框并不完全包含整个2分钟的数据.例如:

2010-01-21 15:08:00    0.044
2010-01-22 05:10:00    0.102
Run Code Online (Sandbox Code Playgroud)

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

unu*_*tbu 7

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

您可以在8天内计算2秒积分的数量:

window_size = pd.Timedelta('8D')/pd.Timedelta('2min')
Run Code Online (Sandbox Code Playgroud)

然后用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())
Run Code Online (Sandbox Code Playgroud)

产量

                          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
Run Code Online (Sandbox Code Playgroud)

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

df['std'].resample('D', how='mean')
Run Code Online (Sandbox Code Playgroud)

产量

...
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
Run Code Online (Sandbox Code Playgroud)

在上面,我们计算了滚动标准偏差,然后重新采样到具有每日频率的时间序列.

如果我们重新采样原始数据每天频率第一,然后计算滚动标准偏差,则一般而言,结果会有所不同.

另请注意,您的数据看起来每天都有相当多的变化,因此通过采用均值进行重新采样可能(错误地?)隐藏该变化.所以最好先计算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())
Run Code Online (Sandbox Code Playgroud)

产量

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
Run Code Online (Sandbox Code Playgroud)

扩展时间序列的替代方法是编写代码以计算每个8天窗口的正确子系列.虽然这是可能的,但是您必须为时间序列的每一行计算这一事实可能会使此方法非常慢.因此,我认为更快的方法是扩展时间序列.