我将一年中的某一天转换为日期,我注意到这as.Date通常会让意外(对我而言)结果.为什么我会为这些命令得到这样不同的答案?
as.Date(x = 1, format = '%j', origin= '2015-01-01')
Run Code Online (Sandbox Code Playgroud)
回报 "2018-07-21"
as.Date(x = 1, origin= '2015-01-01')
Run Code Online (Sandbox Code Playgroud)
回报 "2015-01-02"
as.Date(x = 1, format = '%j', origin= as.Date('2015-01-01'))
Run Code Online (Sandbox Code Playgroud)
回报 "2015-01-02"
as.Date(x = '1',format = '%j', origin= '2015-01-01')
Run Code Online (Sandbox Code Playgroud)
回报 "2018-01-01"
as.Date(x = '1', origin= '2015-01-01')
Run Code Online (Sandbox Code Playgroud)
返回错误: Error in charToDate(x) :
character string is not in a standard unambiguous format
小智 3
我试图通过查看methods下各种定义的定义S3 generic as.Date,以及通过 RStudio 调试代码并查看调用函数的历史记录来部分回答下面的问题。
as.Date.numeric和as.Date.character的定义as.Date.default在答案的底部提供。
我定义了自己的函数check来调试发生的情况。
check <- function() {
as.Date(x = 1, format = '%j', origin= '2015-01-01')
as.Date(x = 1, origin= '2015-01-01')
}
Run Code Online (Sandbox Code Playgroud)
在第一次调用中,UseMethodofas.Date被调用,并将其分派给as.Date.numeric。as.Date(origin, ...)这又是现在被分派到的调用as.Date.character。如果您查看 的源代码as.Date.character,则条件为 FALSE,因为本例中已提供if missing(format)格式。%j所以被调用的代码是strptime(x, format, tz = "GMT"). 这将返回最后一次调用2018-07-20 IST转换为的值。请注意,时区可能会根据您所在的国家/地区而有所不同。内部调用无法使用此过程进行调试的 C 函数。2018-07-20as.Datestrptime
在第二次调用中,主要区别在于用户未提供格式字符串。因此,按照上述相同的过程,当条件为 TRUE 时,调用的是charToDate内部定义的函数as.Date.character,而不是内部定义的函数。在这种情况下,尝试默认格式并在 中找到匹配项。在这种情况下,提供正确的格式并计算正确的值。现在将其添加到其中,即 1 - 记住字符版本是由代码所在的数字版本调用的。这提供了正确的答案。strptimeif missing(format)charToDate'%Y-%m-%dstrptime2015-01-01xas.Date(origin, ...) + x
虽然它没有为您的问题提供完整的答案,但一般情况是它在很大程度上取决于传递给 的格式字符串strptime。希望这可以帮助。
as.日期.数字
function (x, origin, ...)
{
if (missing(origin))
stop("'origin' must be supplied")
as.Date(origin, ...) + x
}
Run Code Online (Sandbox Code Playgroud)
as.日期.字符
function (x, format, tryFormats = c("%Y-%m-%d", "%Y/%m/%d"),
optional = FALSE, ...)
{
charToDate <- function(x) {
xx <- x[1L]
if (is.na(xx)) {
j <- 1L
while (is.na(xx) && (j <- j + 1L) <= length(x)) xx <- x[j]
if (is.na(xx))
f <- "%Y-%m-%d"
}
if (is.na(xx))
strptime(x, f)
else {
for (ff in tryFormats) if (!is.na(strptime(xx, ff,
tz = "GMT")))
return(strptime(x, ff))
if (optional)
as.Date.character(rep.int(NA_character_, length(x)),
"%Y-%m-%d")
else stop("character string is not in a standard unambiguous format")
}
}
res <- if (missing(format))
charToDate(x)
else strptime(x, format, tz = "GMT")
as.Date(res)
}
Run Code Online (Sandbox Code Playgroud)
as.Date.default
function (x, ...)
{
if (inherits(x, "Date"))
x
else if (is.logical(x) && all(is.na(x)))
.Date(as.numeric(x))
else stop(gettextf("do not know how to convert '%s' to class %s",
deparse(substitute(x)), dQuote("Date")), domain = NA)
}
Run Code Online (Sandbox Code Playgroud)