as.integer() 在 int64 数据帧上产生意外结果

as.integer() on an int64 dataframe produces unexpected result

我在审查一些代码时遇到了这个奇怪的结果。如果你有一个数据帧,其中一个值为整数类型,并将其强制为整数,你会得到我认为你期望的结果:

library(dplyr)

tibble(x = as.integer(c(1))) %>% as.integer()

[1] 1

但是如果它是 int64 类型,你会得到一些奇怪的东西:

library(bit64)

tibble(x = as.integer64(c(1))) %>% as.integer()

[1] 0

什么给?我认为它与 int64 class 有关。但为什么我会得到零呢?这只是糟糕的错误处理吗?

更新

好的,当您在 int64 数据帧上调用 dput 时,会提示发生了什么:

structure(list(x = structure(4.94065645841247e-324, 
                             class = "integer64")), 
          row.names = c(NA, -1L), 
          class = c("tbl_df", "tbl", "data.frame"))

所以 as.integer() 正确地将 4.94065645841247e-324 转换为零。但是为什么那是存储在 DF 中的内容?

此外,为了证明这不是 bit64 问题,我从数据库中得到的实际 df 得到了一个非常相似的结构:

structure(list(max = structure(2.78554211125295e-320,
                               class = "integer64")),
          class = "data.frame", 
          row.names = c(NA, -1L))

我认为这是 bit64 的限制。 bit64 使用 S3 方法 as.integer.integer64 将 int64 转换为 int,但仅限于向量(不同于可应用于其他对象的基数 as.integer)。基数 as.integer 不知道如何在 data.frame 或其他情况下将 int64 转换为 int。

因此在加载 bit64 之后,as.integer 将在所有 int64 向量上实际调用 as.integer.integer64,但不会在 data.frame 或 tibble 上调用。