Как проверить, существует ли эта дата без сломанного конвейера данных в R? - PullRequest
0 голосов
/ 11 июля 2020

У меня есть конвейер данных в R, и я застрял с ошибкой преобразования строки в дату для несуществующей даты в будущем

s_date <- "2021-02-29"    
as.Date(s_date, origin = "1970-01-01")

Этот код генерирует ошибку «Ошибка в charToDate (x) : символьная строка не в стандартном однозначном формате "

Вот более подробный код из конвейера:

# Fixed month and day
date_month <- "2"
date_day <- "29"

# Loop by years
for(date_year in c("2020", "2021")) {

   s_date <- paste0(date_year, "-", date_month, "-", date_day)

   # BUG
   date_selected <- as.Date(s_date, origin = "1970-01-01")

}

Как можно обработать эту ошибку без сломанного конвейера. Например, добавив следующую действительную дату «2021-03-01».

Спасибо!

Ответы [ 2 ]

2 голосов
/ 11 июля 2020

Вы можете попробовать ISOdate, что даст NA, а не ошибку.

as.Date(do.call(ISOdate, as.list(el(strsplit("2020-02-29" , "-")))))
# [1] "2020-02-29"
as.Date(do.call(ISOdate, as.list(el(strsplit("2021-02-29" , "-")))))
# [1] NA

Ваш l oop может выглядеть примерно так:

date_month <- "2"
date_day <- "29"
date_year <- c("2020", "2021")
r <- `class<-`(integer(), "Date")

for (i in seq(date_year)) {
  d <- as.Date(ISOdate(date_year[i], date_month, date_day))
  d <- if (is.na(d)) {
    as.Date(ISOdate(date_year[i], as.numeric(date_month) + 1, 1))
  } else d
  r[i] <- d
}
r
# [1] "2020-02-29" "2021-03-01"
2 голосов
/ 11 июля 2020

В этом решении используется пакет lubridate. Код сначала проверяет, является ли дата в for l oop действительной, и, если нет, вызывает вспомогательную функцию nextDate.

nextDate <- function(y, m, d){
  y <- as.integer(y)
  m <- as.integer(m)
  d <- as.integer(d)
  days <- lubridate::days_in_month(paste(y, m, 1, sep = "-"))
  as.Date(paste(y, m, min(days, d), sep = "-")) + 1L
}

date_month <- "2"
date_day <- "29"

# Loop by years
for(date_year in c("2020", "2021")) {
  s_date <- paste0(date_year, "-", date_month, "-", date_day)
  # 
  repeat{
    date_selected <- tryCatch(as.Date(s_date, origin = "1970-01-01"),
                              error = function(e) e
    )
    if(inherits(date_selected, "error")){
      s_date <- nextDate(date_year, date_month, date_day)
    }else break
  }
}

Посмотреть результат.

s_date
#[1] "2021-03-01"
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...