r - 为什么 as.character() 在日期列表上返回一个整数?

标签 r string date

我很惊讶地观察到 R 中的以下行为:

as.character(c(Sys.Date()))
#> [1] "2018-02-05"

as.character(list(Sys.Date()))
#> [1] "17567"

为什么会发生这种情况?也就是说,显然“17567”是 as.integer(Sys.Date) 的结果,但我不遵循为什么 as.character(list(Sys.Date())) 的逻辑应该结束调用 as.integer() .

(通常字符串被视为整数可以归咎于没有设置options(stringsAsFactors=FALSE) ,但这里似乎并非如此。)

编辑 :正如 Josh 观察到的,这是由于 as.vector 的潜在行为,但我没有发现更直观:
as.vector(Sys.Date())
#> 17567
as.vector(Sys.Date(), "character")
#> "17567"

为什么? (是的,我相信日期在较低级别的内部结构中存储为整数,但在这种情况下这种强制转换为文字整数而没有警告对我来说似乎令人惊讶)。

这也以更微妙的方式表现出来:
tbl <- tibble:::as_data_frame(list(col1 = list(Sys.Date(), "stuff")))
df <- as.data.frame(tbl)
df
#>    col1
#> 1 17567
#> 2 stuff

df[1, 1]
#> [[1]]
#> [1] "2018-02-05"

注意data.frame的打印方法将日期显示为整数,而实际上它是一个列表列并且日期仍然是日期。

目前尚不清楚在这种情况下打印方法发生了什么,以及为什么它显示出如此误导性的数据表示。

编辑 :

Date 类出人意料地脱落的其他示例,暴露了基础数字基类型:
vapply(list(Sys.Date()), I, Sys.Date())
vapply(list(Sys.Date()), lubridate::as_date, Sys.Date())

以及我目前最喜欢的:
unlist(list(Sys.Date()))

看来矢量操作与 Date (和 POSIX 对象)是脆弱的;应该关注mode/typeof而不是 class预测向量的行为方式。

最佳答案

该问题最终与函数 as.vector() 的行为有关。 .

申请时as.character()到一个列表,它看到一个类 "list" 的对象(不是类 "Date" 之一)。由于没有as.character()列表方法,默认方法 as.character.default被派送。它执行以下操作:

as.character.default
# function (x, ...) 
# .Internal(as.vector(x, "character"))
# <bytecode: 0x0000000006793e88>
# <environment: namespace:base>

如您所见,它首先通过将数据对象强制转换为向量来准备数据对象。运行 as.vector()直接在 Date 对象列表上显示,反过来,它是产生强制转换为整数然后转换为字符的原因。
as.vector(list(Sys.Date()), "character")
# [1] "17567"

正如卡尔指出的那样,上面的解释即使准确,也并不令人满意。更完整的答案需要查看幕后发生的事情,在调用 .Internal(as.vector(x, "character")) 执行的 C 代码中。 .所有相关的 C 代码都在源文件 coerce.c 中.

首先是 do_asvector() 其中调用 ascommon() 其中调用 coerceVector() 其中调用 coerceVectorList() 然后,最后, coerceToString() . coerceToString() examines the "typeof"它正在处理的元素,在我们的例子中,看到它是一个“REAL”切换到 this code block :
case REALSXP:
PrintDefaults();
savedigits = R_print.digits; R_print.digits = DBL_DIG;/* MAX precision */
for (i = 0; i < n; i++) {
//  if ((i+1) % NINTERRUPT == 0) R_CheckUserInterrupt();
    SET_STRING_ELT(ans, i, StringFromReal(REAL(v)[i], &warn));
}
R_print.digits = savedigits;
break;

以及为什么它将块用于类型为 REALSXP 的对象?因为那是 R Date 的存储模式对象(可以通过执行 mode(Sys.Date())typeof(Sys.Date()) 看到)。

实际情况是这样的:在上述事件链中,列表的元素没有以某种方式被捕获并作为 "Date" 处理。在 R 函数调用和方法调度领域中的对象。相反,它们作为 "list" 传递(又名 VECSXP )到一系列 C 函数。到那时,为时已晚,因为处理该列表的 C 函数对 "Date" 一无所知。其元素的类。特别是最终转换为字符的函数,coerceToCharacter()只看到元素的存储模式,即 REAL/numeric/double,并把它们当作 处理。全部 他们是。

关于r - 为什么 as.character() 在日期列表上返回一个整数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48631580/

相关文章:

R 滞后于缺失数据

r - R 中的 Bray-Curtis 成对分析

c++ - 在库类(std::string)上使用 memset 时出现 "undefined behaviors"的原因是什么?

java - 从 JFrame 输入 'Date' 到 MySQL 数据库

mysql - 查询以找出每个员工的出生日期

R:列数未知的行的最小值和最大值

r - 通过ID计算时差

c# - 如何使用 C# 替换字符串中的多个单词?

string - 为什么 "[[ ' >' > ' 0' ]]"返回 false 而 "[ ' >'\> ' 0' ]"返回 true?

Python:使用日历将日期编号转换为日期名称