Есть ли более элегантный способ конвертировать двузначные годы в четырехзначные годы с lubridate?
Если вектор даты имеет двузначные годы, mdy()
составляет годы между 00 и 68 в 21 век и годы между 69 и 99 годами до 20-го века. Например:
library(lubridate)
mdy(c("1/2/54","1/2/68","1/2/69","1/2/99","1/2/04"))
дает следующий результат:
Multiple format matches with 5 successes: %m/%d/%y, %m/%d/%Y.
Using date format %m/%d/%y.
[1] "2054-01-02 UTC" "2068-01-02 UTC" "1969-01-02 UTC" "1999-01-02 UTC" "2004-01-02 UTC"
Я могу исправить это после факта, вычитая 100 из неправильных дат, чтобы повернуть 2054 и 2068 в 1954 и 1968 годах. Но есть ли более элегантный и менее подверженный ошибкам метод разбора двухзначных дат, чтобы они обрабатывались правильно в самом процессе анализа?
Обновление: После того, как @JoshuaUlrich указал мне на strptime
, я нашел этот вопрос, который касается проблемы, подобной моей, но используя основание R.
Похоже, что отличное дополнение к обработке даты в R будет каким-то образом справляться с отменой выбора периода в течение двухзначных дат в функциях синтаксического анализа даты.
Ответы
Ответ 1
Вот функция, которая позволяет вам сделать это:
library(lubridate)
x <- mdy(c("1/2/54","1/2/68","1/2/69","1/2/99","1/2/04"))
foo <- function(x, year=1968){
m <- year(x) %% 100
year(x) <- ifelse(m > year %% 100, 1900+m, 2000+m)
x
}
Попробуйте:
x
[1] "2054-01-02 UTC" "2068-01-02 UTC" "1969-01-02 UTC" "1999-01-02 UTC"
[5] "2004-01-02 UTC"
foo(x)
[1] "2054-01-02 UTC" "2068-01-02 UTC" "1969-01-02 UTC" "1999-01-02 UTC"
[5] "2004-01-02 UTC"
foo(x, 1950)
[1] "1954-01-02 UTC" "1968-01-02 UTC" "1969-01-02 UTC" "1999-01-02 UTC"
[5] "2004-01-02 UTC"
Битва магии здесь заключается в том, чтобы использовать оператор модуля %%
, чтобы вернуть дробную часть деления. Итак, 1968 %% 100
дает 68.
Ответ 2
Я просто испытал эту ту же ошибку/функцию.
В конце концов я написал следующие две быстрые функции, которые помогут конвертировать из дат типа excel (именно там я и получаю это) к тому, что R может использовать.
Нет ничего плохого в принятом ответе - просто я предпочитаю не загружать слишком много пакетов.
Во-первых, помощник для разделения и замены лет...
year1900 <- function(dd_y, yrFlip = 50)
{
dd_y <- as.numeric(dd_y)
dd_y[dd_y > yrFlip] <- dd_y[dd_y > yrFlip] + 1900
dd_y[dd_y < yrFlip] <- dd_y[dd_y < yrFlip] + 2000
return(dd_y)
}
который используется функцией, которая "фиксирует" ваши даты excel, в зависимости от типа:
XLdate <- function(Xd, type = 'b-Y')
{
switch(type,
'b-Y' = as.Date(paste0(substr(Xd, 5, 9), "-", substr(Xd, 1, 3), "-01"), format = "%Y-%b-%d"),
'b-y' = as.Date(paste0(year1900(substr(Xd, 5, 6)), "-", substr(Xd, 1, 3), "-01"),
format = "%Y-%b-%d"),
'Y-b' = as.Date(paste0(substr(Xd, 1, 3), "-", substr(Xd, 5, 9), "-01"), format = "%Y-%b-%d")
)
}
Надеюсь, это поможет.
Ответ 3
Другой вариант:
xxx <- c("01-Jan-54","01-Feb-68","01-Aug-69","01-May-99","01-Jun-04", "
31-Dec-68","01-Jan-69", "31-Dec-99")
.
dmy(paste0(sub("\\d\\d$","",xxx) , ifelse( (tt <-
sub("\\d\\d-\\D\\D\\D-","",xxx) ) > 20 ,paste0("19",tt),paste0("20",tt))))
Хотя решение не изящно и коротко.
Я думаю, было бы лучше, если бы lubridate просто добавил опцию, чтобы указать дату отсечения.