【发布时间】:2016-10-04 03:47:52
【问题描述】:
所以我是 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))
【问题讨论】:
-
我可以在 data.table 1.9.6 上复制它。
aggregate也给出 26 行,但data.table给出 21。使用by=as.character(obscure_math)也给出正确的 26 行 -
我也可以使用 v1.9.7 进行复制
-
@thelatemail 我不确定这是否重要。包不应该在这样的操作中改变用户数据的值。
by变量的值应该被改变是非常不透明的。我的猜测是这与优化基数排序有关,但没有人应该期望这种操作会损失精度(在这种情况下完全不可用)。 -
我们建议使用
bit64::integer64处理 64 位整数(而不是双精度数)。请参阅?setNumericRounding(和示例)了解我们为什么要四舍五入最后 2 个字节。有一个与此相关的问题(但 w.r.t. 订购 data.table,而不是分组),但我们还没有时间了解如何最好地处理它,#1642。 -
@Arun 哇。这让我大吃一惊,默认情况下,您在这些操作中舍入所有双精度数的最后 16 位。据我所知,这是一个糟糕的设计决定。您正在对“大量数字”的构成做出非常大的假设。令人失望。请添加为答案,以便我接受并关闭此问题。
标签: r data.table