2012-05-18 14 views
20

Wie der Titel geht. Warum ist die Lubridate-Funktion so viel langsamer?Warum sind Lubridate-Funktionen im Vergleich zu as.POSIXct so langsam?

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

Ich lasse jemanden, der mehr Erfahrung chime hat, aber meine Vermutung ist, dass lubridate Funktionen entwickelt werden, um eine Menge Dinge" hinter den Kulissen "zu behandeln, was bedeutet es mehr Überprüfung/Überprüfung der Eingabe zu versuchen und geben Sie vernünftige Ergebnisse. Lesen der [Hintergrunddokumente] (https://github.com/hadley/lubridate) hallt diese Gefühle. Ob das zur Langsamkeit beiträgt oder nicht, bin ich nicht sicher ... aber das wäre In ähnlicher Weise ist die 'plyr'-Familie aus Bequemlichkeitsgründen ebenfalls geschrieben und kann unter bestimmten Umständen relativ schlecht im Vergleich zu den Basisfunktionen funktionieren ... aber es ist einfach zu benutzen! – Chase

+0

@ RJ- Es wäre viel besser, wenn Sie tatsächlich hätten Code in Ihrer Frage, der den Unterschied zeigt. "system.time" kann verwendet werden, um zu messen. – Tommy

+0

Notiert. wird es in Kürze veröffentlichen. – JackeJR

Antwort

38

Aus den gleichen Gründen Autos sind langsam im Vergleich zu riding on top of rockets. Die zusätzliche Benutzerfreundlichkeit und Sicherheit macht Autos viel langsamer als eine Rakete, aber Sie werden weniger in die Luft gehen und es ist einfacher zu starten, zu steuern und ein Auto zu bremsen. In der richtigen Situation (z. B. muss ich zum Mond gelangen) ist die Rakete das richtige Werkzeug für den Job. Wenn jemand ein Auto mit einer Rakete erfunden hätte, hätten wir etwas.

Beginnen Sie mit der Suche, was dmy tut, und Sie werden den Unterschied für die Geschwindigkeit (übrigens von Ihrem bechmarks würde ich nicht sagen, dass lubridate ist, dass viel langsamer, da diese in Millisekunden) sehen:

ich sehe parse_date und num_to_date und make_format

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

Sogleich:

dmy #type dies in der Befehlszeile und Sie erhalten. Wundert sich, was all diese Jungs sind. Mal sehen:

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 wir haben strsplit-ting, expand-ing.grid-s, paste-ing, ifelse-ing, unname-ing usw. plus eine Whole Lotta Error Checking Going On (spielen auf dem Zep-Song). Also, was wir hier haben, ist ein schöner syntaktischer Zucker. Mmmmm lecker aber es kommt mit einem Preis, Geschwindigkeit.

Vergleichen Sie das mitas.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) 

viel mehr internen Codierung Es gibt und weniger Fehlerprüfung mit as.POSICct los So haben Sie uns erleichtern fragen wollen und Sicherheit oder Geschwindigkeit und Leistung? Kommt auf den Job an.

+6

+1 Große Antwort. Haben Sie auch bemerkt, dass 'parse_date()' selbst 'as.POSIXct()' aufruft? Am Ende hat das 'dmy()' Auto eine 'as.POSIXct()' Engine unter der Haube. –

+2

Ich denke, es ist tatsächlich mit 'as.POSIXct.default' ein Zeichenargument zu behandeln (' Dates' ist ein Zeichenvektor). –

+0

Wer diese Antwort abgelehnt hat, scheint seltsam, denn 24 andere fanden es hilfreich. Könnten Sie einen Einblick in Ihre Wahl geben? –

8

@ Tylers Antwort ist korrekt. Hier einige weitere Informationen einschließlich einer Spitze auf Herstellung lubridate schneller - aus der Hilfedatei.

"Lubridate hat einen eingebauten sehr schnell POSIX-Parser, portiert von der fasttime Paket von Simon Urbanek ist diese Funktionalität noch optional und konnte mit Optionen aktiviert werden (lubridate.fasttime = TRUE). Lubridate wird automatisch POSIX-Strings erkennen und schnelle Parser anstelle der Standard-Strptime-Dienstprogramm verwenden."

Verwandte Themen