Альтернативы для применения одного и того же условия к нескольким переменным внутри функции case_when - PullRequest
2 голосов

Я пытаюсь найти более эффективное или элегантное решение для множественного кондиционирования внутри функции case_when.

Я создаю фиктивный столбец на основе нескольких условий в определенных столбцах фрейма данных. Во многих случаях я использую один и тот же is.na() для многих столбцов. У меня правильный результат, но я пробовал другие подходы с apply, reduce и anyNa без успеха.

Скажем, этот фрейм данных выглядит как данные, над которыми я работаю:

set.seed(12)
dframe <- data.frame(
  x1 = sample(letters[1:2], 10, replace = TRUE),
  x2 = sample(0:1, 10, replace = TRUE),
  x3 = sample(0:2, 10, replace = TRUE),
  x4 = sample(0:2, 10, replace = TRUE),
  x5 = sample(0:2, 10, replace = TRUE),
  x6 = sample(0:2, 10, replace = TRUE)
) %>% 
  mutate_if(is.numeric, list(~na_if(., 2)))

И это выглядит так:

   x1 x2 x3 x4 x5 x6
1   b  1 NA  0  0  0
2   b  0  0  0 NA NA
3   b  1  0  0  0  1
4   a  0 NA  1 NA  0
5   a  1  1 NA NA NA
6   b  0 NA  1  1  1
7   a  1  1 NA NA  0
8   a  1  0  1 NA  0
9   b  1 NA NA  0  0
10  b  1  1  0 NA NA

Затем я создаю столбец x7 на основе следующих условий:

dframe %>% 
  mutate(
    x7 = case_when(
      x2 == 1 & 
      (!is.na(x3) | !is.na(x4) | !is.na(x5)) & 
      !is.na(x6) ~ 1,
      x2 == 1 ~ 0,
      TRUE ~ NA_real_
    )
  )

в результате:

   x1 x2 x3 x4 x5 x6 x7
1   b  1 NA  0  0  0  1
2   b  0  0  0 NA NA NA
3   b  1  0  0  0  1  1
4   a  0 NA  1 NA  0 NA
5   a  1  1 NA NA NA  0
6   b  0 NA  1  1  1 NA
7   a  1  1 NA NA  0  1
8   a  1  0  1 NA  0  1
9   b  1 NA NA  0  0  1
10  b  1  1  0 NA NA  0

Однако я хочу найти альтернативу для записи (!is.na(x3) | !is.na(x4) | !is.na(x5)), потому что в моем реальном сценарии я должен напечатать это для 11 столбцов.

Я пытался использовать complete.cases(x3, x4, x5), но это не соответствует логике, которую я использую в коде.

Использование anyNA(x3, x4, x5) бросков Error in anyNA(x3, x4, x5) : anyNA takes 1 or 2 arguments.

Также попробовал ответы аналогичной проблемы , но так как я не использую его для фильтрации, он не сработал.

Может быть, я обдумываю это, но я ищу что-то без использования (!is.na(x3) | !is.na(x4) | !is.na(x5)).

1 Ответ

1 голос
/ 20 мая 2019

Мы могли бы использовать rowSums и указать столбцы по имени

library(dplyr)

dframe %>% 
  mutate(x7 = case_when(
               x2 == 1 & 
               rowSums(!is.na(.[c("x3","x4","x5")])) > 0 &
               !is.na(x6) ~ 1,
               x2 == 1 ~ 0,
               TRUE ~ NA_real_
              )
          )

Или по позиции

rowSums(!is.na(.[3:5])) > 0

Мы могли бы сделать это также с использованием инвертированной логики.

rowSums(is.na(.[c("x3","x4","x5")])) != 3

Или

rowSums(is.na(.[3:5])) != 3

Здесь мы используем 3, так как для проверки в данном примере есть 3 столбца (x3, x4 и x5), вы можетеизмените число на основе вашего фактического количества столбцов (11).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...