r - case_when in mutate pipe




dplyr (4)

Beachten Sie zusätzlich zu der obigen Antwort von @ akrun, dass die schließende Klammer für case_when() nicht in eine eigene Zeile gesetzt werden kann.

Zum Beispiel funktioniert das OK:

mtcars %>%  
   mutate(cg = case_when(
      .$carb <= 2 ~ "low",  .$carb > 2 ~ "high")) 

aber das tut nicht:

mtcars %>%  
   mutate(cg = case_when(
      .$carb <= 2 ~ "low",  .$carb > 2 ~ "high")
      ) 

https://code.i-harness.com

Es scheint, dass sich dplyr::case_when nicht wie andere Befehle in einem dplyr::mutate Aufruf dplyr::mutate . Zum Beispiel:

library(dplyr)

case_when(mtcars$carb <= 2 ~ "low",
          mtcars$carb > 2 ~ "high") %>% 
  table

funktioniert:

.
high  low 
  15   17 

Aber lege case_when in eine mutate Kette:

mtcars %>% 
  mutate(cg = case_when(carb <= 2 ~ "low",
                        carb > 2 ~ "high"))

und du bekommst:

 Error: object 'carb' not found

während dies gut funktioniert

mtcars %>% 
  mutate(cg = carb %>% 
           cut(c(0, 2, 8)))

In meinem Fall hat Quasiquotation sehr geholfen. Sie können im Voraus eine Reihe von Formeln in Anführungszeichen erstellen, die die Mutationsregeln definieren (und entweder bekannte Spaltennamen wie in der ersten Formel verwenden oder von !! profitieren und Regeln dynamisch wie in der zweiten Formel erstellen), die dann innerhalb von mutate - verwendet werden. case_when Kombination wie hier

    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

Ich bevorzuge eine solche Lösung, weil sie die Erstellung komplexer Regeln ermöglicht, z. B. die Verwendung von map2 mit LHS-Bedingungen und RHS-Werten, um Formeln in map2 zu map2

    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

und verwenden Sie es an verschiedenen Orten, indem Sie es auf verschiedene Datensätze anwenden, ohne jedes Mal, wenn Sie eine komplexe Mutation benötigen, alle Regeln manuell eingeben zu müssen.

Als endgültige Antwort auf das Problem lösen 7 zusätzliche Symbole und zwei Klammern das Problem

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

Erstellt am 16.01.2019 durch das Paket reprex (v0.2.1.9000)



Wir können .$ Verwenden

mtcars %>%  
     mutate(cg = case_when(.$carb <= 2 ~ "low",  .$carb > 2 ~ "high")) %>%
    .$cg %>%
    table()
# high  low 
#  15   17 






dplyr