Подтвердить что ты не робот

Есть ли более элегантный способ конвертировать двузначные годы в четырехзначные годы с 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 будет каким-то образом справляться с отменой выбора периода в течение двухзначных дат в функциях синтаксического анализа даты.

4b9b3361

Ответ 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 просто добавил опцию, чтобы указать дату отсечения.