2012-05-18 10 views
20

Come dice il titolo. Perché la funzione lubridate è molto più lenta?Perché le funzioni di lubrificazione sono così lente se confrontate con as.POSIXct?

library(lubridate) 
library(microbenchmark) 

Dates <- sample(c(dates = format(seq(ISOdate(2010,1,1), by='day', length=365), format='%d-%m-%Y')), 50000, replace = TRUE) 

microbenchmark(as.POSIXct(Dates, format = "%d-%b-%Y %H:%M:%S", tz = "GMT"), times = 100) 
microbenchmark(dmy(Dates, tz ="GMT"), times = 100) 

Unit: milliseconds 
expr               min   lq   median  uq   max 
1 as.POSIXct(Dates, format = "%d-%b-%Y %H:%M:%S", tz = "GMT") 103.1902 104.3247 108.675  109.2632 149.871 
2 dmy(Dates, tz = "GMT")          184.4871 194.1504 197.8422 214.3771 268.4911 
+4

Lascerò a qualcuno che ha più esperienza, ma penso che le funzioni di lubridate siano progettate per gestire un sacco di cose" dietro le quinte ", il che significa che fanno più controllo/controllo dell'input da provare e dare risultati ragionevoli.La lettura dei [documenti di base] (https://github.com/hadley/lubridate) riecheggia questi sentimenti.Se non contribuisca alla lentezza, non sono sicuro ... ma sarebbe Allo stesso modo, anche la famiglia 'plyr' è scritta per comodità e potrebbe funzionare relativamente male rispetto alle funzioni base in determinate circostanze ... ma è facile da usare! – Chase

+0

@ RJ- Sarebbe molto meglio se tu avessi codice nella tua domanda che mostra la differenza. "system.time' può essere usato per misurare. – Tommy

+0

Notato. lo posterò tra poco. – JackeJR

risposta

38

Per le stesse vetture ragione sono lenti in confronto a riding on top of rockets. La maggiore facilità d'uso e sicurezza rendono le auto molto più lente di un razzo, ma è meno probabile che si gonfino ed è più facile iniziare, sterzare e frenare una macchina. Tuttavia, nella giusta situazione (ad esempio, ho bisogno di arrivare sulla luna) il razzo è lo strumento giusto per il lavoro. Ora se qualcuno ha inventato una macchina con un razzo legato al tetto avremmo qualcosa.

Inizia con guardare a ciò che sta facendo dmy e vedrete la differenza per la velocità (a proposito dai vostri bechmarks Non direi che lubridate è che molto più lento in quanto questi sono in millisecondi):

dmy #type questo nella riga di comando e si ottiene:

>dmy 
function (..., quiet = FALSE, tz = "UTC") 
{ 
    dates <- unlist(list(...)) 
    parse_date(num_to_date(dates), make_format("dmy"), quiet = quiet, 
     tz = tz) 
} 
<environment: namespace:lubridate> 

Subito vedo parse_date e num_to_date e make_format. Ci si chiede cosa siano tutti questi ragazzi. Vediamo:

parse_date

> parse_date 
function (x, formats, quiet = FALSE, seps = find_separator(x), 
    tz = "UTC") 
{ 
    fmt <- guess_format(head(x, 100), formats, seps, quiet) 
    parsed <- as.POSIXct(strptime(x, fmt, tz = tz)) 
    if (length(x) > 2 & !quiet) 
     message("Using date format ", fmt, ".") 
    failed <- sum(is.na(parsed)) - sum(is.na(x)) 
    if (failed > 0) { 
     message(failed, " failed to parse.") 
    } 
    parsed 
} 
<environment: namespace:lubridate> 

num_to_date

> getAnywhere(num_to_date) 
A single object matching ‘num_to_date’ was found 
It was found in the following places 
    namespace:lubridate 
with value 

function (x) 
{ 
    if (is.numeric(x)) { 
     x <- as.character(x) 
     x <- paste(ifelse(nchar(x)%%2 == 1, "0", ""), x, sep = "") 
    } 
    x 
} 
<environment: namespace:lubridate> 

make_format

> getAnywhere(make_format) 
A single object matching ‘make_format’ was found 
It was found in the following places 
    namespace:lubridate 
with value 

function (order) 
{ 
    order <- strsplit(order, "")[[1]] 
    formats <- list(d = "%d", m = c("%m", "%b"), y = c("%y", 
     "%Y"))[order] 
    grid <- expand.grid(formats, KEEP.OUT.ATTRS = FALSE, stringsAsFactors = FALSE) 
    lapply(1:nrow(grid), function(i) unname(unlist(grid[i, ]))) 
} 
<environment: namespace:lubridate> 

Wow abbiamo ottenuto strsplit-ting, expand-ing.grid-s, paste-ing, ifelse-ing, unname-ing ecc. Più un errore di Lotta intero Controllo in corso (riproduzione della canzone Zep). Quindi quello che abbiamo qui è un bel zucchero sintattico. Mmmmm gustoso ma ha un prezzo, velocità.

Confronti che, peras.POSIXct:

getAnywhere(as.POSIXct) #tells us to use methods to see the business 
methods('as.POSIXct') #tells us all the business 
as.POSIXct.date   #what I believe your code is using (I don't use dates though) 

C'è molto di più di codifica interna e meno controllo degli errori in corso con as.POSICct quindi bisogna chiedere voglio la facilità e la sicurezza o la velocità e la potenza? Dipende dal lavoro

+6

+1 Ottima risposta. Inoltre, hai notato che 'parse_date()' chiama 'as.POSIXct()'? Alla fine, la macchina 'dmy()' ha un motore 'as.POSIXct()' sotto il cofano. –

+2

Penso che in realtà usi 'as.POSIXct.default' per gestire un argomento di carattere (' Date' è un vettore di caratteri). –

+0

Chi ha mai downvoted questa risposta sembra strano poiché 24 altri l'hanno trovato utile. Potresti dare qualche idea della tua scelta? –

8

@ La risposta di Tyler è corretta. Ecco qualche informazione in più tra cui una punta sul rendere lubridate più veloce - dal file di aiuto:.

"Lubridate ha un insito parser POSIX molto veloce, portato dal pacchetto fasttime da Simon Urbanek Questa funzionalità è ancora facoltativo e potrebbe essere attivato con le opzioni (lubridate.fasttime = TRUE). Lubridate rileva automaticamente le stringhe POSIX e utilizza un parser veloce anziché l'utilità strptime predefinita."

Problemi correlati