如何从(相对)非结构化文本中提取日期[R]

ver*_*his 1 string grep r date

我很难从字符串中提取日期.该字符串可以看作多种方式之一,但总是包含以下形式:

<full month name> <numeric date>, <year>
Run Code Online (Sandbox Code Playgroud)

如:

DECEMBER 4, 2011
Run Code Online (Sandbox Code Playgroud)

但是,字符串开头的文本范围很广,采用所有这些形式:

THE PUBLIC SCHEDULE FOR MAYOR RAHM EMANUEL JUNE 9, 2011
THE PUBLIC SCHEDULE FOR MAYOR RAHM EMANUEL FOR OCTOBER 29 & OCTOBER 30, 2011
The Public Schedule for Mayor Rahm Emanuel December 17, 2011 through January 2, 2012
The Public Schedule for Mayor Rahm Emanuel December 8th and 9th, 2012
The Public Schedule for Mayor Rahm Emanuel – March 13, 2013
Run Code Online (Sandbox Code Playgroud)

这些变化真的让我失望.通常情况下,我只是删除字符串的前X个字符,并使用余数作为我的日期,但由于格式不断变化,这是不可能的.我一直试图改变这种情况,但我最终创造了同样多的问题.

这似乎grep()可能是在这里使用的函数,但我真的不明白我如何创建一个模式来捕获这些日期,或如何使用它的输出.

感谢您的任何帮助!

Sim*_*nek 5

这或多或少只是一种启发式方法.如果你删除了一个月的所有内容,我们将获得更易于管理的内容.让我们假设您的示例行位于变量中b:

months.regex <- paste(month.name, collapse='|')
d <- gsub(paste0(".*(", months.regex, ")"), "\\1", 
          b[grep(months.regex, b, TRUE)], TRUE)
Run Code Online (Sandbox Code Playgroud)

这样只选择一个月的行并删除截至月份的所有内容:

> d
[1] "JUNE 9, 2011"               "OCTOBER 30, 2011"          
[3] "January 2, 2012"            "December 8th and 9th, 2012"
[5] "March 13, 2013"            
Run Code Online (Sandbox Code Playgroud)

月份和年份相当容易提取:

month <- match(tolower(gsub("\\s.*", "", d)), tolower(month.name))
day <- gsub("\\S+\\s+(.*),.*", "\\1", d)
year <- as.integer(gsub(".*,\\s*(\\d{4})", "\\1", d))
Run Code Online (Sandbox Code Playgroud)

真正的问题是自由形式的日子和多个日期.没有完美的方法 - 如果行中超过一个月,上面将总是选择最后一个日期.为了减少多天,您可以使用类似的东西

day <- as.integer(gsub("\\D.*", "", day))
Run Code Online (Sandbox Code Playgroud)

如果有多个,那将选择第一天.完整的结果是:

> paste(month.name[month], day, year)
[1] "June 9 2011"     "October 30 2011" "January 2 2012"  "December 8 2012"
[5] "March 13 2013"  
Run Code Online (Sandbox Code Playgroud)