2012-05-18 32 views
20

Khi tiêu đề xuất hiện. Tại sao hàm lubridate chậm hơn nhiều?Tại sao hàm lubridate quá chậm khi so sánh với.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

Tôi sẽ cho phép người có nhiều kinh nghiệm hơn, nhưng tôi đoán là các hàm lubridate được thiết kế để xử lý nhiều thứ" đằng sau hậu trường "có nghĩa là sẽ kiểm tra/kiểm tra đầu vào để thử Đọc các [tài liệu nền] (https://github.com/hadley/lubridate) vang vọng những tình cảm này, cho dù điều đó có gây phiền toái cho sự chậm chạp, tôi không chắc ... nhưng đó sẽ là Tương tự như vậy, gia đình 'plyr' được viết để thuận tiện và có thể hoạt động tương đối kém so với các chức năng cơ bản trong một số trường hợp ... nhưng rất dễ sử dụng! – Chase

+0

@ RJ- Sẽ tốt hơn nếu bạn có thực tế mã trong câu hỏi của bạn cho thấy sự khác biệt. 'system.time' có thể được sử dụng để đo lường – Tommy

+0

Lưu ý, sẽ đăng lên một cách nhanh chóng – JackeJR

Trả lời

38

Vì lý do tương tự, xe hơi chậm so với riding on top of rockets. Việc sử dụng dễ dàng và an toàn làm cho chiếc xe chậm hơn nhiều so với một tên lửa nhưng bạn ít có khả năng bị thổi bay và dễ dàng hơn để bắt đầu, lái và phanh xe. Tuy nhiên, trong tình huống đúng (ví dụ, tôi cần lên mặt trăng) tên lửa là công cụ thích hợp cho công việc. Bây giờ nếu ai đó phát minh ra một chiếc xe với một tên lửa gắn vào mái nhà, chúng tôi sẽ có một cái gì đó.

Bắt đầu với nhìn vào những gì dmy đang làm và bạn sẽ thấy sự khác biệt cho tốc độ (bằng cách từ bechmarks của bạn tôi sẽ không nói rằng lubridate là chậm như những nhiêu trong mili giây):

dmy #type này vào dòng lệnh và bạn nhận được:

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

Ngay lập tức tôi thấy parse_datenum_to_datemake_format. Làm cho một người tự hỏi tất cả những kẻ này là gì. Hãy xem:

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> 

Chà, chúng tôi nhận được strsplit-ting, expand-ing.grid-s, paste-ing, ifelse-ing, unname-ing v.v. cộng với Kiểm tra lỗi toàn bộ lỗi khi phát (phát trên bài hát Zep). Vì vậy, những gì chúng tôi có ở đây là một số đường cú pháp đẹp. Mmmmm ngon nhưng nó đi kèm với một mức giá, tốc độ.

Hãy so sánh đó đểas.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ó rất nhiều mã hóa nội bộ và ít kiểm tra lỗi xảy ra với as.POSICct Vì vậy, bạn đã hỏi tôi muốn xoa dịu và an toàn hoặc tốc độ và sức mạnh? Phụ thuộc vào công việc.

+6

+1 Câu trả lời hay. Ngoài ra, bạn có nhận thấy rằng 'parse_date()' tự gọi 'as.POSIXct()'? Vì vậy, cuối cùng, xe 'dmy()' có một động cơ 'as.POSIXct()' dưới mui xe. –

+2

Tôi nghĩ rằng nó thực sự đang sử dụng 'as.POSIXct.default' để xử lý một đối số ký tự (' Ngày 'là một vectơ ký tự). –

+0

Ai đã từng đánh giá thấp câu trả lời này có vẻ lạ vì 24 người khác thấy nó hữu ích. Bạn có thể cung cấp cho một số cái nhìn sâu sắc vào sự lựa chọn của bạn? –

8

@ Câu trả lời của Tyler là chính xác. Dưới đây là một số thông tin hơn bao gồm một tip về làm lubridate nhanh - từ tập tin giúp đỡ:.

"Lubridate có một phân tích cú pháp POSIX rất nhanh inbuilt, chuyển từ gói fasttime bởi Simon Urbanek Chức năng này như được nêu ra tùy chọn và có thể được kích hoạt với các tùy chọn (lubridate.fasttime = TRUE) Lubridate sẽ tự động phát hiện các chuỗi POSIX và sử dụng nhanh phân tích cú pháp thay vì tiện ích strptime mặc định."

Các vấn đề liên quan