【发布时间】:2019-09-20 16:23:58
【问题描述】:
我想在R 中以字符串形式(例如:“09/20/2019”)转换大约 1 亿个日期。
在做
a = "09/20/2019"
a <- as.Date(a, "%m/%d/%Y")
似乎有点慢。有没有更快的方法来实现这种转换?
(尝试了fasttime 包,但它需要以下顺序:year, month, day... 因此原始字符串需要进一步操作)
【问题讨论】:
我想在R 中以字符串形式(例如:“09/20/2019”)转换大约 1 亿个日期。
在做
a = "09/20/2019"
a <- as.Date(a, "%m/%d/%Y")
似乎有点慢。有没有更快的方法来实现这种转换?
(尝试了fasttime 包,但它需要以下顺序:year, month, day... 因此原始字符串需要进一步操作)
【问题讨论】:
对于此示例数据,使用查找表方法 (1) 比 as.Date 快 38 倍。对于这个示例数据,方法 (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
【讨论】:
dd的查找表提前排序也应该节省一点时间
使用润滑
library(lubridate)
a = "09/20/2019"
mdy(a)
【讨论】:
mdy,只用了 0.22 秒。
lubridate:::C_parse_dt 可能比使用通用 strptime 的 as.Date 更快。我对 C 方面的了解还不够,无法更根本地发表评论
既然你提到了fasttime,我就好奇地想用其他一些常见的选项来测试它。它需要年月日格式的日期,但您可以使用一些正则表达式来做到这一点。
我对一组较小但仍然很麻烦的日期进行了基准测试。我在一台使用了一年的 MacBook Pro 上运行了很多其他的东西,并且还在 100 万次约会中进行了 100 次试验,并且在我吃完三明治之前完成了所有 3 种方法。
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,因此由于没有设置时间元素,因此将其添加到其中 - 删除它可能会成为另一个耗时的步骤。
【讨论】: