序数日期的格式?

时间:2016-08-30 21:23:20

标签: r date

我错过了什么吗?我无法弄清楚如何将以下内容转换为Date s:

ord_dates <- c("September 1st, 2016", "September 2nd, 2016",
               "September 3rd, 2016", "September 4th, 2016")

?strptime似乎没有列出序数后缀的简写,并且不会自动处理:

as.Date(ord_dates, format = c("%B %d, %Y"))
#[1] NA NA NA NA

是否有用于处理format参数中被忽略字符的标记?我失踪了一个令牌?

我能想到的最好的是(可能是一个较短的正则表达式,但同样的想法):

as.Date(gsub("([0-9]+)(st|nd|rd|th)", "\\1", ord_dates), format = "%B %d, %Y")
# [1] "2016-09-01" "2016-09-02" "2016-09-03" "2016-09-04"

似乎这类数据应该比较常见;我错过了什么吗?

1 个答案:

答案 0 :(得分:5)

享受lubridate的力量:

library(lubridate)    
mdy(ord_dates)

[1] "2016-09-01" "2016-09-02" "2016-09-03" "2016-09-04"

在内部,lubridate没有任何特殊的转换规范可以启用此功能。相反,lubridate首先使用(通过智能猜测)格式"%B %dst, %Y"。这将获得ord_dates的第一个元素。

然后检查NA并重复其对其余元素的智能猜测,在"%B %dnd, %Y"上建立以获得第二个元素。它以这种方式继续,直到没有NA s(这种情况在4次迭代后发生),或直到它的智能猜测未能找到可能的格式候选者。

你可以想象这会让lubridate变得更慢,而且它只是使用上面@alistaire建议的智能正则表达式的速度的一半:

set.seed(109123)
ord_dates <- sample(
  c("September 1st, 2016", "September 2nd, 2016",
    "September 3rd, 2016", "September 4th, 2016"),
  1e6, TRUE
  )

library(microbenchmark)

microbenchmark(times = 10L,
               lubridate = mdy(ord_dates),
               base = as.Date(sub("\\D+,", "", ord_dates),
                              format = "%B %e %Y"))
# Unit: seconds
#       expr      min       lq     mean   median       uq      max neval cld
#  lubridate 2.167957 2.219463 2.290950 2.252565 2.301725 2.587724    10   b
#       base 1.183970 1.224824 1.218642 1.227034 1.228324 1.229095    10  a 

lubridate的明显优势在于它的简洁性和灵活性。