creo que es justo que as.Date
convierte character
a través Date
POSIXlt
, utilizando strptime
. Y strptime
es muy lento, creo.
Para rastrearlo a través de usted, escriba as.Date
, luego methods(as.Date)
, luego observe el método 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>
>
¿Por qué es as.POSIXlt(Date)$year+1900
relativamente rápido? De nuevo, rastrearlo a través de:
> 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>
>
Intrigado, profundicemos en Date2POSIXlt. Para este bit, necesitamos grep main/src para saber qué archivo .c debemos ver.
~/R/Rtrunk/src/main$ grep Date2POSIXlt *
names.c:{"Date2POSIXlt",do_D2POSIXlt, 0, 11, 1, {PP_FUNCALL, PREC_FN, 0}},
$
Ahora sabemos que necesitamos buscar 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}},
$
Oh, que podría tener datetime.c adivinado. De todos modos, así que mirando copia más reciente en vivo:
datetime.c
Búsqueda de allí para D2POSIXlt
y verá lo fácil que es pasar de la fecha (numérico) para POSIXlt. También verá cómo POSIXlt es un vector real (8 bytes) más siete vectores enteros (4 bytes cada uno). ¡Eso es 40 bytes, por fecha!
Así que el quid de la cuestión (creo) es por qué strptime
es tan lento, y tal vez eso se puede mejorar en R. O simplemente evitar POSIXlt
, ya sea directa o indirectamente.
Aquí está un ejemplo reproducible usando el número de elementos indicados en cuestión (3000000):
> 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
Pasando tz
parece acelerar strptime
, lo que hace as.Date.character
. Entonces tal vez depende de tu localidad. Pero strptime
parece ser el culpable, no data.table
. Quizás vuelva a ejecutar este ejemplo y vea si le lleva 90 segundos en su equipo.
Es bastante extraño que sea mucho más lento. Debería estar haciendo el equivalente a: dPl <- as.POSIXlt; with (paste (mon, mdate, year, sep = "/") –
Agregué el tiempo por encima de ... – krhlk
¿Has mirado los resultados de la conversión? –