【问题标题】:Numpy, pandas, Matlab, R rolling sum inconsistency, with varying length of historyNumpy、pandas、Matlab、R 滚动和不一致,历史长度不同
【发布时间】:2015-03-28 05:05:49
【问题描述】:

我正在测试日期范围的模拟,以这样一种方式,我期望给定日期的计算返回相同的数字,而不管我计算给定批次的日期范围。

也就是说,如果我在 1990-2000 的范围内调用系统,那么 1995.07.01 的结果应该与在 1995-1996 调用系统时的结果相同。应该很基础吧,我想...

问题在于快速滚动窗口实现会累积舍入误差,这确实取决于滚动窗口之外的历史长度。因此,当我对 1995.07.01 进行 20 天移动求和时,如果对 1990 年以来的时间序列运行滚动求和运算,结果会产生更多的累积舍入误差。

这是一个示例,我希望非 nan 结果完全匹配:

df = pd.DataFrame([xrange(7)]).astype('float64').T
df = np.sqrt(df)
roll1_df = pd.rolling_sum(df, window=3)
roll2_df = pd.rolling_sum(df.iloc[3:, :], window=3)

但我得到了舍入错误:

roll1_df - roll2_df

              0
0           NaN
1           NaN
2           NaN
3           NaN
4           NaN
5  8.881784e-16
6  1.776357e-15

该示例使用 Python/pandas,但在任何数字运算软件中问题都是一样的,因此我很高兴在 pandas、numpy、Matlab、R ... 或基于纯理论的想法。

保持快速滚动操作的性能优势很重要,即避免简单地将所有日期的最后 N 个值相加(这将比快速滚动窗口实现慢 O(N) 倍)。

编辑:解决方案

我毕竟选择了以下解决方案,将 pandas 拆开并在 rolling_sum 中进行一些舍入后重新组合:

rolling_sum_stable_df = _rolling_func(
    lambda *arg_l: np.round(roll_sum(*arg_l), decimals=11),
    'Stable rolling_sum'
)

可以在 rolling_sum() 之前先转换为 float32,然后再转换回 float64,但会丢失更多位数。该方法的缺点是我必须为 rolling_cov 和其他滚动函数执行此操作,这涉及到更多。

【问题讨论】:

  • 我不太确定我明白你到底在总结什么。但是,如果您想要两个结果之间完全相等 - 浮点数永远不会让您满意。您要么必须使用整数类型,要么必须使用“几乎相等”而不是“相等”的实现。
  • 您可以使用 np.isclose : np.isclose(roll1_df[3:], roll2_df ) 这表明最后两个值足够接近,可以认为是相等的
  • 几年前尝试过。不幸的是,系统中的数值误差是非线性的,即 1e-16 的差异可能会导致以后的数字发生较大变化。

标签: matlab numpy pandas numerical-methods moving-average


【解决方案1】:

使用内置的 python decimal 模块。它没有浮点舍入误差。但是,它比浮点数要慢。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-03-26
    • 2015-03-10
    • 2021-06-07
    • 1970-01-01
    • 1970-01-01
    • 2018-05-13
    • 1970-01-01
    相关资源
    最近更新 更多