R的data.table截断位?

sta*_*kam 19 r data.table

所以我是data.tableR的忠实粉丝.我几乎一直都在使用它,但是遇到了一种根本不适合我的情况.我有一个包(我公司内部),它使用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))
Run Code Online (Sandbox Code Playgroud)

Aru*_*run 18

更新:已在data.table(v1.9.7)当前开发版本中删除了默认舍入功能.请参阅此处的 devel版本的安装说明.

这也意味着您有责任理解表示浮点数并处理浮点数的限制.


data.table已存在很长时间了.我们过去常常通过使用阈值来处理浮点表示的限制(例如,基数R就是这样all.equal).然而,它根本不起作用,因为它需要根据比较的数量来自适应.本系列文章是关于此主题和其他潜在问题的精彩读物.

这是一个反复出现的问题,因为a)人们没有意识到这些限制,或者b)门槛并没有真正帮助他们解决问题,这意味着人们不断在这里询问或在项目页面上发帖.

虽然我们重新实现了data.table的快速基数排序顺序,但我们借此机会提供了一种解决问题的替代方法,并提供了一种解决方案,如果它被证明是不合需要的(导出setNumericRounding).对于#1642问题, 排序可能不需要舍入双精度(但它不是那么简单,因为顺序直接影响基于二进制搜索的子集).

这里的实际问题是对浮点数进行分组,更糟糕的是在你的情况下这样的数字.这只是一个糟糕的选择恕我直言.

我可以想到前进的两种方式:

  1. 当对真正加倍的列进行分组时(在R中,1是双倍而不是1L,并且这些情况没有问题),我们提供一个警告,即最后2个字节被舍入,人们应该阅读?setNumericRounding.并建议使用bit64::integer64.

  2. 删除允许对实际双值进行分组操作的功能,或强制它们在继续之前将精度固定为某些数字.我想不出为什么人们想要真正按浮点数分组的一个正当理由(希望听到那些做过的人).

最不可能发生的是回到基于阈值的检查,以确定哪些双打应属于同一组.

为了让Q得到回答,请使用setNumericRounding(0L).

  • 在对双精度进行分组时对显式错误进行大拇指. (7认同)
  • @Arun它也出现在`data.table`源代码中,我可以将`integer64`作为一个类添加到我的列中,并在使用data.table时解决这个问题.再次感谢`data.table`和我的问题所做的所有伟大工作! (2认同)