所以我是R中一个巨大的data.table
粉丝。我几乎一直都在使用它,但却遇到了一个根本不能为我工作的情况。我有一个包(我公司内部)使用R' double
来存储无符号64位整数的值,其位序列对应于某些奇特的编码。这个包在除data.table之外的任何地方都能很好地工作。我发现,如果我在这些数据的列上聚合,我会丢失大量的唯一值。我唯一的猜测是data.table
在某种奇怪的double
优化中截断位。
任何人都可以确认是这种情况吗?这只是一个错误吗?
下面看一下问题的复制品,并与我目前必须使用的套餐进行比较,但希望避免激情(dplyr
)。
temp <- structure(list(obscure_math = c(6.95476896592629e-309, 6.95476863436446e-309,
6.95476743245288e-309, 6.95476942182375e-309, 6.95477149408563e-309,
6.95477132830476e-309, 6.95477132830476e-309, 6.95477149408562e-309,
6.95477174275702e-309, 6.95476880014538e-309, 6.95476896592647e-309,
6.95476896592647e-309, 6.95476900737172e-309, 6.95476900737172e-309,
6.95476946326899e-309, 6.95476958760468e-309, 6.95476958760468e-309,
6.95477020928318e-309, 6.95477124541406e-309, 6.95476859291965e-309,
6.95476875870014e-309, 6.95476904881676e-309, 6.95476904881676e-309,
6.95476904881676e-309, 6.95476909026199e-309, 6.95476909026199e-309,
6.95476909026199e-309, 6.95476909026199e-309, 6.9547691317072e-309,
6.9547691317072e-309, 6.9547691317072e-309, 6.9547691317072e-309,
6.9547691317072e-309, 6.9547691317072e-309, 6.9547691317072e-309,
6.9547691317072e-309, 6.9547691317072e-309, 6.9547691317072e-309,
6.9547691317072e-309, 6.9547691317072e-309, 6.95477211576406e-309,
6.95476880014538e-309, 6.95476880014538e-309, 6.95476880014538e-309,
6.95476892448104e-309, 6.95476880014538e-309, 6.95476892448105e-309,
6.9547689659263e-309, 6.95476913170719e-309, 6.95476933893334e-309
)), .Names = "obscure_math", class = c("data.table", "data.frame"), row.names = c(NA,
-50L))
dt_collapsed <- temp[, .(count=.N), by=obscure_math]
nrow(dt_collapsed) == length(unique(temp$obscure_math))
setDF(temp)
dplyr_collapsed <- temp %>% group_by(obscure_math) %>% summarise(count=n())
nrow(dplyr_collapsed) == length(unique(temp$obscure_math))
答案 0 :(得分:18)
更新:current development version of data.table (v1.9.7)中删除了默认的舍入功能。请参阅开发版here的安装说明。
这也意味着您需要了解表示浮点数和处理浮点数的限制。
data.table已存在很长时间了。我们过去常常通过使用阈值来处理浮点表示的限制(就像基数R那样,例如all.equal
)。然而,它根本不起作用,因为它需要自适应,这取决于所比较的数字有多大。 This series of articles是关于此主题和其他潜在问题的精彩读物。
这是一个反复出现的问题,因为a)人们没有意识到这些限制,或者b)阈值并没有真正帮助他们解决问题,这意味着人们一直在这里问或在帖子上发帖项目页面。
虽然我们重新实现了data.table命令以快速基数排序,但我们借此机会提供了一种解决问题的替代方法,并提供了一种方法,如果它被证明是不合需要的(导出setNumericRounding
) 。对于#1642问题,排序可能不需要进行双精度舍入(但它并不那么简单,因为顺序直接影响基于二进制搜索的子集)。
这里的实际问题是对浮点数进行分组,更糟糕的是在你的情况下这样的数字。这只是一个糟糕的选择恕我直言。
我可以想到前进的两种方式:
当对真正翻倍的列进行分组时(在R中,1是双倍而不是1L,而这些情况没有问题)我们提供一个警告,说明最后2个字节是四舍五入的,人们应该阅读?setNumericRounding
。并建议使用bit64::integer64
。
删除允许分组操作真正双倍值的功能,或强制它们在继续之前将精度修正为某些数字。我无法想出为什么人们会想要通过浮点数进行分组的真实原因(希望听到那些做过的人)。
不太可能发生的情况是返回基于阈值的检查,以确定哪些双打属于同一组。
为了让Q得到解答,请使用setNumericRounding(0L)
。