首页 > 解决方案 > 在 R 中寻求 as.Date() 函数的解释

问题描述

我正在将一年中的某一天转换为日期,我注意到这as.Date通常会返回意想不到的(对我而言)结果。为什么我对这些命令得到如此不同的答案?

as.Date(x =  1, format = '%j', origin= '2015-01-01')

返回"2018-07-21"

as.Date(x = 1, origin= '2015-01-01')

返回"2015-01-02"

as.Date(x =  1, format = '%j', origin= as.Date('2015-01-01'))

返回"2015-01-02"

as.Date(x = '1',format = '%j', origin= '2015-01-01')

返回"2018-01-01"

as.Date(x = '1', origin= '2015-01-01')

返回错误:Error in charToDate(x) : character string is not in a standard unambiguous format

标签: r

解决方案


methods我试图通过查看下的各种定义S3 generic as.Date,以及通过 RStudio 调试您的代码并查看调用函数的历史来部分回答下面的问题。

和的定义在答案as.Date.numeric的底部提供。as.Date.characteras.Date.default

我定义了自己的函数check来调试发生的事情。

check <- function() {

as.Date(x =  1, format = '%j', origin= '2015-01-01')
as.Date(x = 1, origin= '2015-01-01')

}

在第一次调用中,UseMethodofas.Date被调用,它将它分派到as.Date.numeric. 这又是调用as.Date(origin, ...),现在被分派到as.Date.character. 如果您查看 的源代码as.Date.character,则条件if missing(format)为 FALSE,因为%j在这种情况下已提供格式。所以被调用的代码是strptime(x, format, tz = "GMT"). 这将返回最后一次调用2018-07-20 IST转换为. 请注意,时区可能因您所在的国家/地区而异。内部调用无法使用此过程调试的 C 函数。2018-07-20as.Datestrptime

在第二次调用中,主要区别在于用户未提供格式字符串。因此,按照上述相同的过程,调用的是charToDate内部定义的函数,as.Date.character而不是strptime条件if missing(format)为 TRUE。在这种情况下,charToDate尝试默认格式并在'%Y-%m-%d. 在这种情况下,strptime提供正确的格式并计算正确的值2015-01-01。现在添加到x1 - 记住字符版本是由代码所在的数字版本调用的as.Date(origin, ...) + x。这提供了正确的答案。

虽然它没有为您的问题提供完整的答案,但一般的学习是它严重依赖于传递给strptime. 希望这可以帮助。

as.Date.numeric

function (x, origin, ...)
{
  if (missing(origin))
    stop("'origin' must be supplied")
  as.Date(origin, ...) + x
}

as.Date.character

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)
}

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)
}

推荐阅读