【问题标题】:Trouble with cumsum and decimal numberscumsum 和小数的问题
【发布时间】:2022-01-24 16:10:36
【问题描述】:

假设如下代码:

import numpy as np
import pandas as pd
   
df = pd.DataFrame({'A': np.random.randint(0, 10, 10)})
df['B'] = df['A'].diff()

x, x_diff = 1, df['B'].iloc[1:]
df['C'] = np.r_[x, x_diff].cumsum()

   A    B    C
# 0  6  NaN  1.0
# 1  6  0.0  1.0
# 2  0 -6.0 -5.0
# 3  7  7.0  2.0
# 4  5 -2.0  0.0
# 5  3 -2.0 -2.0
# 6  3  0.0 -2.0
# 7  8  5.0  3.0
# 8  8  0.0  3.0
# 9  8  0.0  3.0

C 列的变化如预期的那样漂亮。这似乎没有问题。但是,当我使用十进制数字时,它们会四舍五入为 0,而我最终的起始值根本没有改变。任何想法如何防止这种情况?理论上我可以再次将数字相乘,但有没有更好的方法来解决这个问题?问题演示如下:

import pandas as pd
import numpy as np

df = pd.DataFrame({'A': np.random.randint(0, 10, 10)})/100000000000000


df['B'] = df['A'].diff()

x, x_diff = 1, df['B'].iloc[1:]
df['C'] = np.r_[x, x_diff].cumsum()

#               A             B    C
# 0  9.000000e-14           NaN  1.0
# 1  7.000000e-14 -2.000000e-14  1.0
# 2  1.000000e-14 -6.000000e-14  1.0
# 3  9.000000e-14  8.000000e-14  1.0
# 4  9.000000e-14  0.000000e+00  1.0
# 5  4.000000e-14 -5.000000e-14  1.0
# 6  6.000000e-14  2.000000e-14  1.0
# 7  9.000000e-14  3.000000e-14  1.0
# 8  7.000000e-14 -2.000000e-14  1.0
# 9  0.000000e+00 -7.000000e-14  1.0

【问题讨论】:

  • 这不是十进制数字的问题,而是数字太小的问题。计算机有效地将它们视为零,因为您可以在计算机中处理的数量级差异很小。你所能做的就是让 C 从 0 开始而不是 1,如果这适用于你的用例。
  • 您可以通过查询您的machine epsilon 来检查是否是这种情况:eps = np.finfo(float).eps。你应该得到1+eps >1,但是添加任何小于eps的东西应该是1。你需要用你实际使用的任何数据类型替换float(例如,numpy.float32的eps约为10^- 7)
  • 如果我在 64 位实现上使用您的代码并将精度设置为 16 pd.set_option('precision', 16) 则列 B 可以看到 cumsum 到列 C。或者正如@Puff 所说,从零开始列C 从零开始。另一种显示方式是添加df['D'] = df['C'] - 1

标签: pandas numpy cumsum


【解决方案1】:

感谢您的许多建议。 PUFF 建议使用 0 作为起始值。 Chris 建议的 pd.set_option('precision', 16) 方法也有效。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-03-23
    • 2010-09-22
    • 1970-01-01
    • 1970-01-01
    • 2011-11-16
    • 2019-08-18
    相关资源
    最近更新 更多