我刚刚提到了lubridate::parse_date_time()
的
帮助页面,特别是它的
select_format
论点。但我无法获得它并为自己的用例设计自己的功能。
实际上,我有一些格式的未清理日期向量。为了简单起见,让我们假设,我有
mdy
、dmy
、ymd
和 ydm
格式的日期。
my_dates <- c("1988-02-03", "1988-15-03", "05-12-2023", "5-27-2022")
lubridate::parse_date_time(my_dates, orders = c("dmy","mdy", "ymd", 'ydm'))
#> [1] "1988-03-02 UTC" "1988-03-15 UTC" "2023-05-12 UTC" "2022-05-27 UTC"
在输出中,我希望
dmy
优先于 mdy
并且 ymd
优先于 ydm
。我该怎么做?我的输出应该是-
#> [1] "1988-02-03 UTC" "1988-03-15 UTC" "2023-12-05 UTC" "2022-05-27 UTC"
您可以通过使用 lubridate::parse_date_time() 函数的 select_formats 参数来设置所需的日期格式优先级来实现此目的。
假设您希望“dmy”优先于“mdy”,并且“ymd”优先于“ydm”,您可以这样设计函数:
library(lubridate)
my_dates <- c("1988-02-03", "1988-15-03", "05-12-2023", "5-27-2022")
parsed_dates <- parse_date_time(
my_dates,
orders = c("dmy", "mdy", "ymd", "ydm"),
select_formats = c("dmy", "mdy", "ymd", "ydm")
)
print(parsed_dates)
#> [1] "1988-02-03 UTC" "1988-03-15 UTC" "2023-12-05 UTC" "2022-05-27 UTC"
select_formats 参数允许您指定日期时间格式向量,该向量定义不明确的日期时间解析的优先级。在这里,通过按顺序列出格式“dmy”、“mdy”、“ymd”、“ydm”,您实际上是在告诉函数您想要的格式的优先级。
注意:如果您使用旧版本的 lubridate,则 select_formats 参数可能不可用。在这种情况下,请确保更新到软件包的最新版本。
parse_date_time()
默认情况下会根据提供的 strptime()
生成一组 %Y-%m-%d
日期格式(例如 orders
),针对日期子集对这些格式进行训练,并且这些格式根据训练的匹配数进行排名根据格式中的标记数量和某些标记的存在应用权重的数据。
要使用提供的订单中的
orders
,您可以设置 train = FALSE
。
library(lubridate)
my_dates <- c("1988-02-03", "1988-15-03", "05-12-2023", "5-27-2022")
orders <- c("dmy","mdy", "ymd", 'ydm')
parse_date_time(my_dates, orders, train = FALSE)
[1] "1988-02-03 UTC" "1988-03-15 UTC" "2023-12-05 UTC" "2022-05-27 UTC"
如果您想按预期使用
select_format
参数,那么逐步了解正在发生的情况可能会很有用。如前所述,使用您的日期(或长日期向量情况下的伪随机子集)和提供的 orders
,该函数会生成 strptime 日期时间格式的猜测。
(guesses <- guess_formats(my_dates, orders))
dOmy Omdy Omdy yOmd ydOm ydOm dmy mdy mdy ymd ydm
"%d-%Om-%Y" "%Om-%d-%Y" "%Om-%d-%Y" "%Y-%Om-%d" "%Y-%d-%Om" "%Y-%d-%Om" "%d-%m-%Y" "%m-%d-%Y" "%m-%d-%Y" "%Y-%m-%d" "%Y-%d-%m"
ydm
"%Y-%d-%m"
这些针对训练集进行测试,以查看每种格式返回多少匹配项:
lubridate:::.train_formats(my_dates, guesses, "")
%Om-%d-%Y %Om-%d-%Y %Y-%d-%Om %Y-%d-%Om %m-%d-%Y %m-%d-%Y %Y-%d-%m %Y-%d-%m %d-%Om-%Y %Y-%Om-%d %d-%m-%Y %Y-%m-%d
2 2 2 2 2 2 2 2 1 1 1 1
接下来,它被传递给
.select_formats
函数,对格式进行加权和排名。您可以通过检查未导出的函数来查看应用的默认权重lubridate::.select_formats
:
function (trained, drop = FALSE)
{
nms <- names(trained)
score <- nchar(gsub("[^%]", "", nms)) + grepl("%Y", nms,
fixed = T) * 1.5 + grepl("%y(?!%)", nms, perl = T) *
1.6 + grepl("%[Bb]", nms) * 0.31 + grepl("%Om", nms) *
0.3 + grepl("%Op", nms) * 0.3 + grepl("%Ob", nms) * 0.32
n0 <- trained != 0
if (drop) {
score <- score[n0]
trained <- trained[n0]
}
else {
score[!n0] <- -100
}
names(trained)[order(score, trained, decreasing = T)]
}
因此,当您调用
parse_date_time(my_dates, orders = c("dmy","mdy", "ymd", 'ydm'))
时使用的默认优先级是:
lubridate:::.select_formats(lubridate:::.train_formats(my_dates, guesses, locale = ""))
[1] "%Om-%d-%Y" "%Om-%d-%Y" "%Y-%d-%Om" "%Y-%d-%Om" "%d-%Om-%Y" "%Y-%Om-%d" "%m-%d-%Y" "%m-%d-%Y" "%Y-%d-%m" "%Y-%d-%m"
[11] "%d-%m-%Y" "%Y-%m-%d"
要改变这一点,我们可以使用自定义函数来应用不同的权重,即优先考虑包含
%d-%m
的格式而不是 %m-%d
以及包含 %Y-%m
的格式优先于 %Y-%d
。
my_select <- function(trained, drop = FALSE, ...) {
nms <- names(trained)
score <- nchar(gsub("[^%]", "", nms)) + grepl("^%d-%O?m", nms) * 2 + grepl("^%Y-%O?m", nms, ignore.case = TRUE) * 2
nms[order(score, trained, decreasing = TRUE)]
}
使用这个,现在的首要任务是:
my_select(lubridate:::.train_formats(my_dates, guesses, locale = ""))
[1] "%d-%Om-%Y" "%Y-%Om-%d" "%d-%m-%Y" "%Y-%m-%d" "%Om-%d-%Y" "%Om-%d-%Y" "%Y-%d-%Om" "%Y-%d-%Om" "%m-%d-%Y" "%m-%d-%Y"
[11] "%Y-%d-%m" "%Y-%d-%m"
如果我们在
parse_date_time()
中使用它,我们会得到您想要的结果:
parse_date_time(my_dates, orders, select_formats = my_select)
[1] "1988-02-03 UTC" "1988-03-15 UTC" "2023-12-05 UTC" "2022-05-27 UTC"
或者我们可以使用
parse_date_time2
并将 strptime
格式直接传递给订单:
parse_date_time2(my_dates, orders = c("%d-%m-%Y","%m-%d-%Y", "%Y-%m-%d", '%Y-%d-%m'))
[1] "1988-02-03 UTC" "1988-03-15 UTC" "2023-12-05 UTC" "2022-05-27 UTC"