Создание нового поля с помощью оператора if else в R

#r

#r

Вопрос:

Я пытаюсь создать новое поле на основе оператора if else. В принципе, у меня есть поле «дата» и поле «предполагаемая дата». Я хочу создать новое поле, которое вычисляет разницу (дни) между одним событием и полем даты или предполагаемой даты (если дата равна NA):

 data <- data.frame("DOD" = c("2020-11-09","2020-01-01","2020-11-19",NA), "DOD.est" = c(NA,NA,NA,"2020-02-09"), "event" = c("Thing1","Thing2","Thing3","Thing4"),"eventDate" = c("2019-02-19","2017-08-09",NA,"2019-12-09"))

data$DOD <- as.Date(data$DOD, "%Y-%m-%d")
data$DOD.est <- as.Date(data$DOD.est, "%Y-%m-%d")
data$eventDate <- as.Date(data$eventDate, "%Y-%m-%d")

# If DOD not NA, calculate diff using DOD.  If DOD NA and DOD.est is not NA, use DOD.est to calculate diff
if (!is.na(data$DOD)) {
  data$event_to_death <- as.numeric(data$DOD - data$eventDate) 
} else if (is.na(data$DOD) amp; !is.na(data$DOD.est)) {
  data$event_to_death <- as.numeric(data$DOD.est - data$eventDate)
} 
 

Мой результат:

 DOD           DOD.est        event       eventDate       event_to_death
2020-11-09    NA             Thing1      2019-02-19       629
2020-01-01    NA             Thing2      2017-08-09       875
2020-11-19    NA             Thing3      NA               NA
NA            2020-02-09     Thing4      2019-12-09       NA
 

Для последней строки я бы ожидал, что event_to_death будет иметь вычисление, поскольку DOD равно NA, а DOD.est не является NA. Что я делаю не так?

Ответ №1:

Вы можете попробовать, с ifelse() помощью которого выполняется векторизация. Функция if() хорошо работает для отдельных значений и может вызвать проблемы при работе с переменными. В этом случае лучше использовать ifelse . Вот код в качестве опции для вас:

 #Code
data$event_to_death <- ifelse(!is.na(data$DOD),as.numeric(data$DOD - data$eventDate),
                              ifelse(is.na(data$DOD) amp; !is.na(data$DOD.est),
                                     as.numeric(data$DOD.est - data$eventDate),NA))
 

Вывод:

 data
         DOD    DOD.est  event  eventDate event_to_death
1 2020-11-09       <NA> Thing1 2019-02-19            629
2 2020-01-01       <NA> Thing2 2017-08-09            875
3 2020-11-19       <NA> Thing3       <NA>             NA
4       <NA> 2020-02-09 Thing4 2019-12-09             62
 

Для того, чтобы ваше решение работало, вам нужно указать if() , что условия должны оцениваться на уровне значений (каждой строки), поскольку функция, если найден вектор, используется для оценки условия только для определенных значений. Вам понадобится цикл:

 #Variable
data$event_to_death <- NA
#Loop
for(i in 1:nrow(data))
{
  if (!is.na(data$DOD[i])) {
    data$event_to_death[i] <- as.numeric(data$DOD[i] - data$eventDate[i]) 
  } else if (is.na(data$DOD[i]) amp; !is.na(data$DOD.est[i])) {
    data$event_to_death[i] <- as.numeric(data$DOD.est[i] - data$eventDate[i])
  } 
}
 

Вывод:

 data
         DOD    DOD.est  event  eventDate event_to_death
1 2020-11-09       <NA> Thing1 2019-02-19            629
2 2020-01-01       <NA> Thing2 2017-08-09            875
3 2020-11-19       <NA> Thing3       <NA>             NA
4       <NA> 2020-02-09 Thing4 2019-12-09             62
 

Таким образом, условия оцениваются по каждому значению и if() работают должным образом.

Комментарии:

1. Спасибо, я постараюсь. Но почему это не работает с оператором if else?

2. @DiamondJoe12 Это потому if , что работает на уровне индивидуального значения. Я добавлю краткое описание того, как заставить ваш код работать!

3. @DiamondJoe12 Я добавил обновление, объясняющее, что происходит с вашим кодом и как заставить его работать. Дайте мне знать, работает ли это и понятно ли это!

4. Спасибо! Теперь работаем!