Pandas 滚动标准差产生不一致的结果,并且与 values.std 不同。

7
使用 pandas v1.0.1 和 numpy 1.18.1 版本,我想在时间序列上使用不同的窗口大小来计算滚动均值和标准差。在我工作的数据中,某些连续点的值可能是恒定的,因此根据窗口大小的不同,滚动均值可能等于窗口中的所有值,相应的标准差预期为 0。
但是,我发现在使用相同的 df 时,具有不同的窗口大小会有不同的行为。
最小可复现代码(MWE):
for window in [3,5]:
    values = [1234.0, 4567.0, 6800.0, 6810.0, 6821.0, 6820.0, 6820.0, 6820.0, 6820.0, 6820.0, 6820.0]
    df = pd.DataFrame(values, columns=['values'])
    df.loc[:, 'mean'] = df.rolling(window, min_periods=1).mean()
    df.loc[:, 'std'] = df.rolling(window, min_periods=1).std(ddof=0)
    print(df.info())
    print(f'window: {window}')
    print(df)
    print('non-rolling result:', df['values'].iloc[len(df.index)-window:].values.std())
    print('')

输出:

window: 3
    values         mean          std
0   1234.0  1234.000000     0.000000
1   4567.0  2900.500000  1666.500000
2   6800.0  4200.333333  2287.053757
3   6810.0  6059.000000  1055.011216
4   6821.0  6810.333333     8.576454
5   6820.0  6817.000000     4.966555
6   6820.0  6820.333333     0.471405
7   6820.0  6820.000000     0.000000
8   6820.0  6820.000000     0.000000
9   6820.0  6820.000000     0.000000
10  6820.0  6820.000000     0.000000
non-rolling result: 0.0

window: 5
    values         mean          std
0   1234.0  1234.000000     0.000000
1   4567.0  2900.500000  1666.500000
2   6800.0  4200.333333  2287.053757
3   6810.0  4852.750000  2280.329732
4   6821.0  5246.400000  2186.267193
5   6820.0  6363.600000   898.332366
6   6820.0  6814.200000     8.158431
7   6820.0  6818.200000     4.118252
8   6820.0  6820.200000     0.400000
9   6820.0  6820.000000     0.000021
10  6820.0  6820.000000     0.000021
non-rolling result: 0.0

如预期所料,对于使用窗口大小为3的idx 7、8、9、10,标准差为0。对于窗口大小为5的情况,我期望idx 9和10的结果为0. 但是,结果与0不同。
如果我针对每个窗口大小的最后一个窗口(分别使用idx 8、9、10和6、7、8、9、10)手动计算标准差,我会得到两种情况下的预期结果为0。
有人知道这里可能出了什么问题吗?任何数值注意事项吗?
1个回答

6
似乎在pd.rolling中实现的std()更偏向高性能而不是数值精度。但是,您可以应用np版本的标准差:
df.loc[:, 'std'] = df.rolling(window, min_periods=1).apply(np.std)

结果:

    values          std
0   1234.0     0.000000
1   4567.0  1666.500000
2   6800.0  2287.053757
3   6810.0  2280.329732
4   6821.0  2186.267193
5   6820.0   898.332366
6   6820.0     8.158431
7   6820.0     4.118252
8   6820.0     0.400000
9   6820.0     0.000000
10  6820.0     0.000000

现在精度更高。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接