Как обрабатывать или игнорировать NA при использовании ifelse для изменения нового столбца с несколькими условиями (решено) - PullRequest
2 голосов
/ 26 февраля 2020

Я новичок в dplyr и пытался создать новую составную переменную из трех разных возрастных переменных, используя dplyr и ifelse. Я сделал фрейм данных, чтобы объяснить ситуацию следующим образом:

library(dplyr)

z <- data.frame("j6" = c(6, 19, NA, NA, NA, NA, NA, 8, 20, 20, NA), 
                "j7" = c(27, 20, NA, 7, 19, NA, NA, 20, 30, 9, NA),
                "j8" = c(8, 22, NA, 20, NA, 8, 30, NA, NA, NA, 3))

z <- z %>% 
        mutate(., age_event = NA) %>% 
        mutate(., age_event = ifelse(j6 < 18 | j7 < 18 | j8 < 18, 1, 0))

Мои ожидания:

  • Три столбца (j6, j7 и j8) указывают возраст, и если в срок аренды одного из них не превышает 18 лет, новый столбец (age_event) должен иметь значение «1», в противном случае - 0.
  • И если два из трех столбцов имеют возраст 18 лет или более, и другим является NA, переменная age_event должна быть 0.
  • Аналогично, если один из трех столбцов старше 18 лет, а остальные - NA, переменная age_event должна быть 0.
  • Также это NA, если все три столбца являются NA.

Однако результат и проблемы отображаются следующим образом:

> z
   j6 j7 j8 age_event
1   6 27  8         1
2  19 20 22         0
3  NA NA NA        NA
4  NA  7 20         1
5  NA 19 NA        NA  <-- should be 0, but NA
6  NA NA  8         1
7  NA NA 30        NA  <-- should be 0, but NA
8   8 20 NA         1
9  20 30 NA        NA  <-- should be 0, but NA
10 20  9 NA         1
11 NA NA  3         1

Я хотел бы знать, есть ли способ превратить 5-е, 7-е и 9-е наблюдения выше на 0 с использованием mutate и ifelse. Будем благодарны за любые предложения!


Обновление (27.02.2020): Я нашел решение с pmin при использовании mutate и ifelse:

z <- z %>% 
        mutate(., age_event = ifelse(is.na(j6) & is.na(j7) & is.na(j8), NA,
                              ifelse(pmin(j6, j7, j8, na.rm = T) < 18, 1, 0)))

> z
   j6 j7 j8 age_event
1   6 27  8         1
2  19 20 22         0
3  NA NA NA        NA
4  NA  7 20         1
5  NA 19 NA         0
6  NA NA  8         1
7  NA NA 30         0
8   8 20 NA         1
9  20 30 NA         0
10 20  9 NA         1
11 NA NA  3         1

Ответы [ 2 ]

3 голосов
/ 26 февраля 2020

Вы можете использовать rowMeans() вместо if_else(), который будет обрабатывать все случаи, которые NA.

z %>% 
  mutate(age_event = +(rowMeans(. < 18, na.rm = TRUE) > 0))

   j6 j7 j8 age_event
1   6 27  8         1
2  19 20 22         0
3  NA NA NA        NA
4  NA  7 20         1
5  NA 19 NA         0
6  NA NA  8         1
7  NA NA 30         0
8   8 20 NA         1
9  20 30 NA         0
10 20  9 NA         1
11 NA NA  3         1
2 голосов
/ 26 февраля 2020

Мы можем использовать rowSums для вычисления количества NA значений в строке и числа значений, которые меньше 18. Затем мы можем использовать case_when для назначения чисел на основе различных условий.

library(dplyr)

z %>%
  mutate(calc = rowSums(!is.na(.), na.rm = TRUE),
         ls18 = rowSums(. < 18, na.rm = TRUE), 
         age_event = case_when(calc == 0 & ls18 == 0 ~ NA_integer_,
                               ls18 > 0 ~ 1L, 
                               TRUE ~ 0L)) %>%
   select(-calc, -ls18)

#   j6 j7 j8 age_event
#1   6 27  8         1
#2  19 20 22         0
#3  NA NA NA        NA
#4  NA  7 20         1
#5  NA 19 NA         0
#6  NA NA  8         1
#7  NA NA 30         0
#8   8 20 NA         1
#9  20 30 NA         0
#10 20  9 NA         1
#11 NA NA  3         1
...