将具有混合date格式的variables转换为r中的一种格式

我的数据框样本:

date 1 25 February 1987 2 20 August 1974 3 9 October 1984 4 18 August 1992 5 19 September 1995 6 16-Oct-63 7 30-Sep-65 8 22 Jan 2008 9 13-11-1961 10 18 August 1987 11 15-Sep-70 12 5 October 1994 13 5 December 1984 14 03/23/87 15 30 August 1988 16 26-10-1993 17 22 August 1989 18 13-Sep-97 

我有一个大的数据框与datevariables有多个格式的date。 variables中的大部分格式如上所示 – 还有一些非常罕见的其他格式。 之所以有多种格式,是因为这些数据是从各个不同格式的网站中提取出来的。

我试图使用直接的转换,例如

 strftime(mydf$date,"%d/%m/%Y") 

但如果有多种格式,这种转换将不起作用。 我不想求助于多个gsubtypes的编辑。 我想知道如果我错过了一个更简单的解决scheme?

代码例如:

  structure(list(date = structure(c(12L, 8L, 18L, 6L, 7L, 4L, 14L, 10L, 1L, 5L, 3L, 17L, 16L, 11L, 15L, 13L, 9L, 2L), .Label = c("13-11-1961", "13-Sep-97", "15-Sep-70", "16-Oct-63", "18 August 1987", "18 August 1992", "19 September 1995", "20 August 1974", "22 August 1989", "22 Jan 2008", "03/23/87", "25 February 1987", "26-10-1993", "30-Sep-65", "30 August 1988", "5 December 1984", "5 October 1994", "9 October 1984"), class = "factor")), .Names = "date", row.names = c(NA, -18L), class = "data.frame") 

您可以尝试parse_date_time中的lubridate ,它允许用户使用orders参数指定几个格式顺序来处理异类date时间字符表示。 就像是…

 library(lubridate) parse_date_time(x = df$date, orders = c("dmy", "d BY", "m/d/y"), locale = "eng") 

…应该能够处理你的大部分格式。 请注意, b / B格式是locale敏感的。

这是一个基本的解决scheme:

 fmts <- c("%d-%b-%y", "%d %b %Y", "%d-%m-%Y", "%m/%d/%y") d <- as.Date(as.numeric(apply(outer(DF$date, fmts, as.Date), 1, na.omit)), "1970-01-01") 

我们已经做了简化的假设,每个inputdate恰好有1个格式。 在这个例子中似乎是这种情况,但是如果不能用function(x) c(na.omit(x), NA)[1])replacena.omit function(x) c(na.omit(x), NA)[1])

请注意,一个两位数的年份可能是模糊的,但在这里看起来应该总是在过去,所以如果不是这样的话,我们会减去100年:

  past <- function(x) ifelse(x > Sys.Date(), seq(from=x, length=2, by="-100 year")[2], x) as.Date(sapply(d, past), "1970-01-01") 

对于最后一行的示例数据:

 [1] "1987-02-25" "1974-08-20" "1984-10-09" "1992-08-18" "1995-09-19" [6] "1963-10-16" "1965-09-30" "2008-01-22" "1961-11-13" "1987-08-18" [11] "1970-09-15" "1994-10-05" "1984-12-05" "1987-03-23" "1988-08-30" [16] "1993-10-26" "1989-08-22" "1997-09-13"