Case_when в мутантной трубе
Кажется, что dplyr::case_when
не ведет себя как другие команды в вызове dplyr::mutate
. Например:
library(dplyr)
case_when(mtcars$carb <= 2 ~ "low",
mtcars$carb > 2 ~ "high") %>%
table
работы:
.
high low
15 17
Но поместите case_when
в цепочку mutate
:
mtcars %>%
mutate(cg = case_when(carb <= 2 ~ "low",
carb > 2 ~ "high"))
и вы получите:
Error: object 'carb' not found
пока это прекрасно работает
mtcars %>%
mutate(cg = carb %>%
cut(c(0, 2, 8)))
Ответы
Ответ 1
Начиная с версии 0.7.0
от dplyr
, case_when
работает в mutate
следующим образом:
library(dplyr) # >= 0.7.0
mtcars %>%
mutate(cg = case_when(carb <= 2 ~ "low",
carb > 2 ~ "high"))
Для получения дополнительной информации: http://dplyr.tidyverse.org/reference/case_when.html
Ответ 2
Мы можем использовать .$
mtcars %>%
mutate(cg = case_when(.$carb <= 2 ~ "low", .$carb > 2 ~ "high")) %>%
.$cg %>%
table()
# high low
# 15 17
Ответ 3
Благодаря @sumedh: @hadley объяснил, что это известный недостаток case_when
:
case_when()
все еще несколько экспериментирует и в настоящее время не работает внутри mutate()
. Это будет исправлено в будущей версии.
Ответ 4
В моем случае квазиквотация очень помогла. Вы можете заранее создать набор формул в кавычках, которые определяют правила мутации (и либо использовать известные имена столбцов, как в первой формуле, либо использовать !!
и динамически создавать правила, как во второй формуле), который затем используется в mutate
- case_when
комбинация как здесь
library(dplyr)
library(rlang)
pattern <- quos(gear == 3L ~ "three", !!sym("gear") == 4L ~ "four", gear == 5L ~ "five")
# Or
# pattern <- list(
# quo(gear == 3L ~ "three"),
# quo(!!sym("gear") == 4L ~ "four"),
# quo(gear == 5L ~ "five"))
#
mtcars %>% mutate(test = case_when(!!!pattern)) %>% head(10L)
#> mpg cyl disp hp drat wt qsec vs am gear carb test
#> 1 21.0 6 160.0 110 3.90 2.620 16.46 0 1 4 4 four
#> 2 21.0 6 160.0 110 3.90 2.875 17.02 0 1 4 4 four
#> 3 22.8 4 108.0 93 3.85 2.320 18.61 1 1 4 1 four
#> 4 21.4 6 258.0 110 3.08 3.215 19.44 1 0 3 1 three
#> 5 18.7 8 360.0 175 3.15 3.440 17.02 0 0 3 2 three
#> 6 18.1 6 225.0 105 2.76 3.460 20.22 1 0 3 1 three
#> 7 14.3 8 360.0 245 3.21 3.570 15.84 0 0 3 4 three
#> 8 24.4 4 146.7 62 3.69 3.190 20.00 1 0 4 2 four
#> 9 22.8 4 140.8 95 3.92 3.150 22.90 1 0 4 2 four
#> 10 19.2 6 167.6 123 3.92 3.440 18.30 1 0 4 4 four
Я предпочитаю такое решение, потому что оно позволяет создавать сложные правила, например, используя map2
с условиями LHS и значениями RHS для генерации цитируемых формул
library(rlang)
library(purrr)
map2(c(3, 4, 5), c("three", "four", "five"), ~quo(gear == !!.x ~ !!.y))
#> [[1]]
#> <quosure>
#> expr: ^gear == 3 ~ "three"
#> env: 0000000014286520
#>
#> [[2]]
#> <quosure>
#> expr: ^gear == 4 ~ "four"
#> env: 000000001273D0E0
#>
#> [[3]]
#> <quosure>
#> expr: ^gear == 5 ~ "five"
#> env: 00000000125870E0
и использование его в разных местах, применение к различным наборам данных без необходимости вручную вводить все правила каждый раз, когда вам нужна сложная мутация.
Создано в 2019-01-16 пакетом представлением (v0.2.1.9000)
Ответ 5
В дополнение к ответу @akrun выше, имейте в виду, что закрывающая скобка для case_when()
не может помещаться в ее собственную строку.
Например, это работает нормально:
mtcars %>%
mutate(cg = case_when(
.$carb <= 2 ~ "low", .$carb > 2 ~ "high"))
но это не так:
mtcars %>%
mutate(cg = case_when(
.$carb <= 2 ~ "low", .$carb > 2 ~ "high")
)
Ответ 6
библиотека (dplyr) # загрузка пакета dplyr
content150_fortified <- content150 %>% #creating a new variable
mutate(number_yn = case_when( #creating a new column using mutate
number >= 18 & number <=25 ~ "no", # if number is "none", make number_yn "no"
number!="none" ~ "yes" # if number is not "none", make number_yn "yes"
)
)