Mutate, через и case_when

У меня возникли проблемы с правильной работой mutate, through и case_when, я воссоздал простую версию своей проблемы здесь:

a <- c(1:10)
b <- c(2:11)
c <- c(3:12)

test <- tibble(a, b, c)

# A tibble: 10 x 3
       a     b     c
   <int> <int> <int>
 1     1     2     3
 2     2     3     4
 3     3     4     5
 4     4     5     6
 5     5     6     7
 6     6     7     8
 7     7     8     9
 8     8     9    10
 9     9    10    11
10    10    11    12

Моя цель - заменить все тройки на четверки, а все остальное оставить прежним. У меня такой код:

test_1 <- 
  test %>% 
  mutate(across(a:c, ~ case_when(. == 3 ~ 4)))

# A tibble: 10 x 3
       a     b     c
   <dbl> <dbl> <dbl>
 1    NA    NA     4
 2    NA     4    NA
 3     4    NA    NA
 4    NA    NA    NA
 5    NA    NA    NA
 6    NA    NA    NA
 7    NA    NA    NA
 8    NA    NA    NA
 9    NA    NA    NA
10    NA    NA    NA

Это близко, но я получаю значения NA, в которых я хочу сохранить значение в исходном тибле. Как сохранить исходные значения с помощью изменения структуры?

Заранее спасибо!


person RobBot    schedule 17.01.2021    source источник
comment
Если условие не выполняется в операторе case_when, оно возвращает NA. Поэтому, если вы не хотите NA, когда . != 3, вам нужно указать это явно с помощью TRUE ~ ..   -  person Ronak Shah    schedule 17.01.2021
comment
Спасибо @RonakShah за объяснение - лично я считаю этот синтаксис действительно неинтуитивным, потому что вы ожидаете, что FALSE ~ . укажет, когда условие НЕ выполняется. Вы можете понять это, только если вы интерпретируете все предыдущие случаи как операторы if-else, поэтому последний оператор улавливает все условия, которые НЕ были выполнены (и, следовательно, ИСТИНА, если НЕ выполняются).   -  person Agile Bean    schedule 10.06.2021


Ответы (3)


Это тоже работает:

a <- c(1:10)
b <- c(2:11)
c <- c(3:12)

tibble(a, b, c) %>% 
  modify(~ ifelse(. == 3, 4, .))

# A tibble: 10 x 3
       a     b     c
   <dbl> <dbl> <dbl>
 1     1     2     4
 2     2     4     4
 3     4     4     5
 4     4     5     6
 5     5     6     7
 6     6     7     8
 7     7     8     9
 8     8     9    10
 9     9    10    11
10    10    11    12
person Alvaro Morales    schedule 07.02.2021

Как насчет этого?

> test %>%
+   mutate(across(a:c, ~ case_when(. == 3 ~ 4, TRUE ~ 1 * (.))))
# A tibble: 10 x 3
       a     b     c
   <dbl> <dbl> <dbl>
 1     1     2     4
 2     2     4     4
 3     4     4     5
 4     4     5     6
 5     5     6     7
 6     6     7     8
 7     7     8     9
 8     8     9    10
 9     9    10    11
10    10    11    12

or

> test %>%
+   replace(. == 3, 4)
# A tibble: 10 x 3
       a     b     c
   <int> <int> <int>
 1     1     2     4
 2     2     4     4
 3     4     4     5
 4     4     5     6
 5     5     6     7
 6     6     7     8
 7     7     8     9
 8     8     9    10
 9     9    10    11
10    10    11    12
person ThomasIsCoding    schedule 17.01.2021
comment
Ваш первый ответ на высоте! Спасибо. Заменить - еще одна отличная идея, но это немного сложно, если вам нужно заменить несколько значений в столбцах, скажем, a: b, а не c. (По крайней мере, я не мог понять этого ...) - person RobBot; 19.01.2021

В base R мы можем сделать

test[test ==3] <- 4
person akrun    schedule 17.01.2021