Преобразование переменной со смешанными форматами даты в один формат
Образец моего фрейма:
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
У меня есть большой фреймворк с переменной даты, которая имеет несколько форматов для дат. Большинство форматов в переменной показаны выше - есть пара очень редких и других. Причина, по которой существует несколько форматов, заключается в том, что данные были сведены с разных сайтов, каждый из которых использовал разные форматы.
Я попытался использовать простые преобразования, например.
strftime(mydf$date,"%d/%m/%Y")
но такие преобразования не будут работать, если есть несколько форматов. Я не хочу прибегать к множественному редактированию типа gsub. Мне было интересно, не хватает ли мне более простого решения?
Код, например:
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")
Ответы
Ответ 1
Вы можете попробовать parse_date_time
в пакете lubridate
, который "позволяет пользователю указывать несколько форматных заказов для обработки разнородных представлений символов даты и времени" с использованием аргумента orders
. Что-то вроде...
library(lubridate)
parse_date_time(x = df$date,
orders = c("d m y", "d B Y", "m/d/y"),
locale = "eng")
... должен иметь возможность обрабатывать большинство ваших форматов. Обратите внимание, что b
/b
форматы locale
чувствительны.
Ответ 2
Вот базовое решение:
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")
Мы сделали упрощающее предположение, что ровно 1 формат работает для каждой даты ввода. Это похоже на пример, но если не заменить na.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"