解析R中复杂的日期文本

解析R中复杂的日期文本,r,parsing,R,Parsing,我想从一些文本内容中提取所有日期。内容由如下日期文本组成: 21, 17, 16, 12, 10, 6, 5, 3 June 2019, 30 and 28, 27 May 2019 我希望在列表()中保留所有日期,如下所示: c("2019-06-21", "2019-06-17", "2019-06-16", "2019-06-12", "2019-06-10", "2019-06-06", "2019-06-05", "2019-06-03", "2019-05-30", "2019-0

我想从一些文本内容中提取所有日期。内容由如下日期文本组成:

21, 17, 16, 12, 10, 6, 5, 3 June 2019, 30 and 28, 27 May 2019
我希望在列表()中保留所有日期,如下所示:

c("2019-06-21", "2019-06-17", "2019-06-16", "2019-06-12", "2019-06-10", "2019-06-06", "2019-06-05", "2019-06-03", "2019-05-30", "2019-05-28", "2019-05-27")

这样做可能吗?谢谢。

正如评论中指出的,简单的答案是将数据清理成R能够理解的格式。如果数据是从另一个软件导入的,那么从该软件导入数据通常(如果不是总是)比从R导入数据更容易

也就是说,翻译始终是可能的,尽管对于这些任务,它必须手动完成。下面的示例说明了如何在R中仅使用基本软件包实现这一点

dates <- '21, 17, 16, 12, 10, 6, 5, 3 June 2019, 30 and 28, 27 May 2019'
#split on ', ' and ' and '
split_dates <- strsplit(dates, ", | and ", perl = TRUE)[[1]] 
#Find the dats which contain months and year
long_dates <- which(nchar(split_dates) > 2)
#Function to format dates
make_dates <- function(string){
    string <- unlist(strsplit(string, " "))
    nString <- length(string)
    year <- string[nString]
    month <- string[nString - 1]
    as.Date(paste0(year, month, string[seq(nString - 2)]), format = '%Y%B%d')
}
#Date vector for output
output_Dates <- integer(length(split_dates))
class(output_Dates) <- "Date"
j <- 0
for(i in long_dates){
    output_Dates[j:i] <- make_dates(split_dates[j:i])
    j <- i + 1
}
output_Dates

[1]"2019-06-21" "2019-06-17" "2019-06-16" "2019-06-12" "2019-06-10" "2019-06-06" "2019-06-05" "2019-06-03" "2019-05-30" "2019-05-28" "2019-05-27"

dates为了补充@Oliver answer,有一个解决方案使用
stringr
lubridate
包并实现非常简单的正则表达式

首先,查找月份-年份块(如
“2019年6月”
):

请注意,内置的
month.name
向量应与原始日期字符串中的月份名称相对应。可以通过正确设置区域设置或手动设置月份名称向量来修复不一致性

然后,创建一个函数,将每个月-年块对应的日期转换为日历日期:

ExtractForMonth <- function(list_entry, string_entry) {

    # define the end of a previous month-year block
    if (string_entry %in% 1) {
        block_begin <- 1
    } else {
        # take the end of a previous entry if it is not the first block
        block_begin <- list_entry[(string_entry - 1), 2] + 1
    }

    n_day <- str_sub(date_string, block_begin, list_entry[string_entry, 1] - 1)
    month_year <- str_sub(date_string, 
        list_entry[string_entry, 1], list_entry[string_entry, 2])
    day_date <- str_extract_all(n_day, "\\b\\d+?\\b")
    date_final <- paste0(unlist(day_date), " ", month_year)
    return(lubridate::dmy(date_final))

您如何知道日期是从哪个月/年开始的?例如,第一个值21、
2019-06-21
如何,而不是
2019-07-21
2020-06-21
?您需要修复源数据,最好是在将其引入R之前。
> > mny_loc_list
[[1]]
     start end
[1,]    29  38
[2,]    55  62
[3,]    72  81
ExtractForMonth <- function(list_entry, string_entry) {

    # define the end of a previous month-year block
    if (string_entry %in% 1) {
        block_begin <- 1
    } else {
        # take the end of a previous entry if it is not the first block
        block_begin <- list_entry[(string_entry - 1), 2] + 1
    }

    n_day <- str_sub(date_string, block_begin, list_entry[string_entry, 1] - 1)
    month_year <- str_sub(date_string, 
        list_entry[string_entry, 1], list_entry[string_entry, 2])
    day_date <- str_extract_all(n_day, "\\b\\d+?\\b")
    date_final <- paste0(unlist(day_date), " ", month_year)
    return(lubridate::dmy(date_final))
dates_list <- lapply(
    function(i) ExtractForMonth(list_entry = mny_loc_list[[1]],
        string_entry = i), 
    X = seq(to = nrow(mny_loc_list[[1]])))

print(dates_list)
[[1]]
[1] "2019-06-21" "2019-06-17" "2019-06-16" "2019-06-12" "2019-06-10"
[6] "2019-06-06" "2019-06-05" "2019-06-03"

[[2]]
[1] "2019-05-30" "2019-05-28" "2019-05-27"