在 R 中使用困难的 AM/PM 格式和带有 lubridate 的 REGEX

Working with difficult AM/PM formats and REGEX with lubridate in R

大家好,我希望每个人都过得愉快,我正在尝试在 R 上的 lubridate 中使用一些 AM/PM 格式,但我似乎无法想出一个合适的解决方案,希望你们能纠正请帮帮我!

我有一个巨大的数据集,其中包含 date_time 格式,格式非常罕见,格式如下:

首先是表示日期的数字,其次是月份的缩写,甚至是月份,完整拼写为 12H 时间格式和字符串“a.m”。或“下午”甚至是“点”之间或缺少“点”的更多空格的组合,例如“a.m”来设置示例请看一下这个向量:

dates<-c("02 dec 05:47 a. m", 
"7 November 09:47 p. m.",
"3  jul 12:28 a.m.", 
"23 sept 08:53 a m.", 
"7 may 09:05 PM")

这些弥补了数据集中超过 95% 的罕见日期时间格式我一直在尝试在 R 上使用 lubridate 我正在尝试使用函数

ydm_hm(paste(2021,dates))

这是因为所有日期都是 2021 年,但我总是得到:

[1] NA                        NA                        NA                       
[4] NA                        "2021-05-07 21:05:00 UTC"
Warning message:
 4 failed to parse. 

无法解析的 4 个给我 NAS,唯一一个解析正确的我确实注意到这个有 PM 或 AM 作为大写字母,没有点,但大多数时候我的格式是这样的:

ydm_hm("7 may 09:05 p.m.")

这给了我 NAS...

所以我觉得好像让这个日期成为锻炼的唯一方法是改变结构并使用 REGEX 转换所有“a.m”。只有在分析数据后我才意识到所有“p.m”或“a.m.”组合成“AM”和“PM”。字符串在 12H 时间格式之后的一个或两个空格之后,其长度始终为 5 个字符,因此应该考虑提出 REGEX 模式的内容如下

字符串将以一个或两个数字开始,然后是空格,然后是字母(对于缩写或完整拼写的月份,之后将有空格,然后是 5 个字符(这是 12H 时间格式),然后是字母空格和所有可能的 a.m 和 p.m 格式的点,但我没有运气尝试转换日期的结构..如果你们能帮助我,我会非常感激我不知道是否有是 R 中的一种方法或另一个包,甚至可以在不使用正则表达式的情况下解决这个问题,所以感谢大家的帮助!

我想要的输出是:

"2021-12-02 05;47:00 UTC"
"2021-11-07 09:47:00 UTC"
"2021-07-03 12:28:00 UTC"
"2021-09-23 08:53:00 UTC"
"2021-05-07 21:05:00 UTC"

在这种情况下,parsedate 中的 parse_date 有效

library(parsedate)
parse_date(paste(2021, dates))

-输出

[1] "2021-12-02 05:47:00 UTC"
[2] "2021-11-07 09:47:00 UTC" 
[3] "2021-07-03 12:28:00 UTC"
[4] "2021-09-23 08:53:00 UTC" 
[5] "2021-05-07 21:05:00 UTC"

或者如果第二个值应该是 PM,使用 str_remove 删除 space

library(stringr)
parse_date(paste(2021, str_remove_all(dates,
    "(?<=[A-Za-z])[. ]+(?=[A-Za-z])")))
[1] "2021-12-02 05:47:00 UTC" 
[2] "2021-11-07 21:47:00 UTC" 
[3] "2021-07-03 00:28:00 UTC" 
[4] "2021-09-23 08:53:00 UTC" 
[5] "2021-05-07 21:05:00 UTC"

使用 ydm_hm,问题是其中一种 am/pm 格式显示 spaces 而没有 .,这可能无法解析。我们可以通过删除 spaces

来更改格式
library(lubridate)
library(stringr)
ydm_hm(paste(2021, str_remove_all(dates,
    "(?<=[A-Za-z])[. ]+(?=[A-Za-z])")))
[1] "2021-12-02 05:47:00 UTC" 
[2] "2021-11-07 21:47:00 UTC" 
[3] "2021-07-03 00:28:00 UTC" 
[4] "2021-09-23 08:53:00 UTC" 
[5] "2021-05-07 21:05:00 UTC"

既然你提出了正则表达式的问题,我想我可能会尝试一种方法来做到这一点

library(stringr)

# get boolean for pm dates
pm = str_detect(dates,"(?<=\d\d:\d\d\s{1,2})[pP]",)

# convert dates to dates without am/pm
dates = str_extract(dates,"^.*:\d\d")

# add pm back to pm dates and am to am dates
dates[pm] <- paste(dates[pm], "PM")
dates[!pm] <- paste(dates[!pm], "AM")

# now your orignal approach works
ydm_hm(paste(2021,dates))

输出

[1] "2021-12-02 05:47:00 UTC" "2021-11-07 21:47:00 UTC" "2021-07-03 00:28:00 UTC" "2021-09-23 08:53:00 UTC"
[5] "2021-05-07 21:05:00 UTC"