Il semble dplyr::case_when
ne se comporte pas comme les autres commandes d'un dplyr::mutate
appel. Par exemple:
library(dplyr)
case_when(mtcars$carb <= 2 ~ "low",
mtcars$carb > 2 ~ "high") %>%
table
travaux:
.
high low
15 17
Mais mettez case_when
dans une chaîne mutate
:
mtcars %>%
mutate(cg = case_when(carb <= 2 ~ "low",
carb > 2 ~ "high"))
et vous obtenez:
Error: object 'carb' not found
alors que cela fonctionne bien
mtcars %>%
mutate(cg = carb %>%
cut(c(0, 2, 8)))
À partir de la version 0.7.0
de dplyr
, case_when
fonctionne dans mutate
comme suit:
library(dplyr) # >= 0.7.0
mtcars %>%
mutate(cg = case_when(carb <= 2 ~ "low",
carb > 2 ~ "high"))
Pour plus d'informations: http://dplyr.tidyverse.org/reference/case_when.html
On peut utiliser .$
mtcars %>%
mutate(cg = case_when(.$carb <= 2 ~ "low", .$carb > 2 ~ "high")) %>%
.$cg %>%
table()
# high low
# 15 17
Avec merci à @sumedh: @hadley a expliqué qu'il s'agit d'une lacune connue de case_when
:
case_when()
est encore un peu expérimental et ne fonctionne pas actuellement dansmutate()
. Ce sera corrigé dans une future version.
Dans mon cas, la quasiquotation a beaucoup aidé. Vous pouvez créer à l’avance un ensemble de formules citées définissant les règles de mutation (et utiliser les noms de colonne connus comme dans la première formule ou tirer parti de !!
et créer des règles dynamiquement comme dans la deuxième formule), qui est ensuite utilisé dans mutate
- case_when
combinaison comme ici
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
Je préfère une telle solution car elle permet de créer des règles complexes, par exemple. en utilisant map2
avec les conditions LHS et les valeurs RHS pour générer les formules citées
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
et l'utiliser à différents endroits, en appliquant différents ensembles de données sans avoir à saisir manuellement toutes les règles chaque fois que vous avez besoin d'une mutation complexe.
En guise de réponse finale au problème, 7 symboles supplémentaires et deux parenthèses le résolvent
library(rlang)
library(dplyr)
mtcars %>%
mutate(test = case_when(!!!quos(gear == 3L ~ "three", gear != 3L ~ "not three"))) %>%
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 not three
#> 2 21.0 6 160.0 110 3.90 2.875 17.02 0 1 4 4 not three
#> 3 22.8 4 108.0 93 3.85 2.320 18.61 1 1 4 1 not three
#> 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 not three
#> 9 22.8 4 140.8 95 3.92 3.150 22.90 1 0 4 2 not three
#> 10 19.2 6 167.6 123 3.92 3.440 18.30 1 0 4 4 not three
Créé le 2019-01-16 par le paquetage reprex (v0.2.1.9000)