我认为这只是as.Date
转换character
为Date
via POSIXlt
,使用strptime
. 而且strptime
很慢,我相信。
要自己跟踪它,请键入as.Date
,然后methods(as.Date)
,然后查看character
方法。
> as.Date
function (x, ...)
UseMethod("as.Date")
<bytecode: 0x2cf4b20>
<environment: namespace:base>
> methods(as.Date)
[1] as.Date.character as.Date.date as.Date.dates as.Date.default
[5] as.Date.factor as.Date.IDate* as.Date.numeric as.Date.POSIXct
[9] as.Date.POSIXlt
Non-visible functions are asterisked
> as.Date.character
function (x, format = "", ...)
{
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) || !is.na(strptime(xx, f <- "%Y-%m-%d",
tz = "GMT")) || !is.na(strptime(xx, f <- "%Y/%m/%d",
tz = "GMT")))
return(strptime(x, f))
stop("character string is not in a standard unambiguous format")
}
res <- if (missing(format))
charToDate(x)
else strptime(x, format, tz = "GMT") #### slow part, I think ####
as.Date(res)
}
<bytecode: 0x2cf6da0>
<environment: namespace:base>
>
为什么as.POSIXlt(Date)$year+1900
比较快?再次,通过以下方式追踪它:
> as.POSIXct
function (x, tz = "", ...)
UseMethod("as.POSIXct")
<bytecode: 0x2936de8>
<environment: namespace:base>
> methods(as.POSIXct)
[1] as.POSIXct.date as.POSIXct.Date as.POSIXct.dates as.POSIXct.default
[5] as.POSIXct.IDate* as.POSIXct.ITime* as.POSIXct.numeric as.POSIXct.POSIXlt
Non-visible functions are asterisked
> as.POSIXlt.Date
function (x, ...)
{
y <- .Internal(Date2POSIXlt(x))
names(y$year) <- names(x)
y
}
<bytecode: 0x395e328>
<environment: namespace:base>
>
感兴趣,让我们深入研究 Date2POSIXlt。对于这一点,我们需要 grep main/src 来知道要查看哪个 .c 文件。
~/R/Rtrunk/src/main$ grep Date2POSIXlt *
names.c:{"Date2POSIXlt",do_D2POSIXlt, 0, 11, 1, {PP_FUNCALL, PREC_FN, 0}},
$
现在我们知道我们需要寻找 D2POSIXlt :
~/R/Rtrunk/src/main$ grep D2POSIXlt *
datetime.c:SEXP attribute_hidden do_D2POSIXlt(SEXP call, SEXP op, SEXP args, SEXP env)
names.c:{"Date2POSIXlt",do_D2POSIXlt, 0, 11, 1, {PP_FUNCALL, PREC_FN, 0}},
$
哦,我们可以猜到 datetime.c。无论如何,看看最新的实时副本:
日期时间.c
在那里搜索D2POSIXlt
,您会发现从 Date(数字)到 POSIXlt 是多么简单。您还将看到 POSIXlt 如何是一个实数向量(8 个字节)加上七个整数向量(每个 4 个字节)。这是 40 个字节,每个日期!
所以问题的症结(我认为)是为什么strptime
这么慢,也许可以在 R 中改进。或者POSIXlt
直接或间接地避免。
这是一个使用相关项目数 (3,000,000) 的可重现示例:
> Range = seq(as.Date("2000-01-01"),as.Date("2012-01-01"),by="days")
> Date = format(sample(Range,3000000,replace=TRUE),"%m/%d/%Y")
> system.time(as.Date(Date, "%m/%d/%Y"))
user system elapsed
21.681 0.060 21.760
> system.time(strptime(Date, "%m/%d/%Y"))
user system elapsed
29.594 8.633 38.270
> system.time(strptime(Date, "%m/%d/%Y", tz="GMT"))
user system elapsed
19.785 0.000 19.802
通过tz
似乎加速strptime
,as.Date.character
确实如此。所以也许这取决于你的语言环境。但strptime
似乎是罪魁祸首,不是data.table
。也许重新运行这个例子,看看你的机器上是否需要 90 秒?