Самый быстрый способ конвертировать строки в даты в R - PullRequest
3 голосов
/ 20 сентября 2019

Я хотел бы преобразовать около 100 миллионов дат в строковой форме (например, «20.09.2009») в R.

Выполнение

a = "09/20/2019"       
a <- as.Date(a, "%m/%d/%Y")

кажется несколько медленным.Есть ли более быстрый способ добиться этого преобразования?

(пробовал пакет fasttime, но ожидает следующий порядок: year, month, day ... поэтому исходная строка нуждается в дополнительных манипуляциях)

Ответы [ 3 ]

8 голосов
/ 20 сентября 2019

Использование метода таблицы поиска (1) в 38 раз быстрее, чем as.Date для данных этого примера.Подход (2) все еще в 18 раз быстрее для этих примеров данных и более удобен, если у вас нет хорошего способа генерации d.Детали ваших данных, конечно же, будут влиять на фактически достигнутую скорость.

# test data
set.seed(123)
d <- format(as.Date("2000-01-01") + 1:100, "%m/%d/%Y")
dd <- sample(d, 1000000, replace = TRUE)

# 1 - lookup table
system.time(as.Date(d, "%m/%d/%Y")[match(dd, d)])
##    user  system elapsed 
##    0.06    0.02    0.07 

# 2 - table lookup generating u on the fly instead of d
system.time({u <- unique(dd); as.Date(u, "%m/%d/%Y")[match(dd, u)] })
## user  system elapsed 
## 0.13    0.03    0.15 

# 3 - as.Date
system.time(as.Date(dd, "%m/%d/%Y"))
##    user  system elapsed 
##    2.61    0.07    2.67 
5 голосов
/ 20 сентября 2019

Поскольку вы упомянули fasttime, мне стало любопытно проверить его на нескольких других распространенных опциях.Для этого требуются даты в формате год-месяц-день, но вы можете сделать это с помощью некоторого регулярного выражения.

Я провел тестирование производительности для небольшого, но все же громоздкого набора дат.Я работаю на MacBook Pro годовалого возраста с множеством других вещей и все еще делаю 100 испытаний на 1 миллион дат со всеми тремя методами, которые были закончены до того, как я съел бутерброд.

set.seed(9)
days <- sample(1:30, 1e6, replace = TRUE)
date_str <- sprintf("09/%02d/2019", days)

# as.Date(date_str, format = "%m/%d/%Y")
# lubridate::mdy(date_str)
# fasttime::fastPOSIXct(gsub("^(\\d{2})/(\\d{2})/(\\d{4})", "\\3-\\1-\\2", date_str))

bench <- microbenchmark::microbenchmark(
  list = list(
    base = as.Date(date_str, format = "%m/%d/%Y"),
    lubr = lubridate::mdy(date_str),
    fast = fasttime::fastPOSIXct(gsub("^(\\d{2})/(\\d{2})/(\\d{4})", "\\3-\\1-\\2", date_str))
  )
)

bench
#> Unit: nanoseconds
#>  expr min lq mean median uq max neval cld
#>  base   3  5 7.02      5  6 180   100   a
#>  lubr   4  5 6.91      6  6 148   100   a
#>  fast   4  5 8.77      5  6 332   100   a

На основев среднем и наименьшем максимуме lubridate::mdy выполняется быстрее всего без необходимости переформатирования или указания строки формата.Исходя из медианы, база as.Date работает быстрее всего, но требует настройки строки форматирования (не имеет значения) или fasttime, но с условием регулярного выражения.Сделайте из этого то, что вы захотите.

Я бы также отметил, что fasttime конвертируется в POSIX, поэтому, так как нет элемента времени, который он устанавливает, его удаление может затем стать другим трудоемким процессом.шаг.

5 голосов
/ 20 сентября 2019

Использование lubridate


library(lubridate)
a = "09/20/2019"
mdy(a)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...