似乎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)))
答案 0 :(得分:36)
自0.7.0
的版本dplyr
开始,case_when
在mutate
内工作如下:
library(dplyr) # >= 0.7.0
mtcars %>%
mutate(cg = case_when(carb <= 2 ~ "low",
carb > 2 ~ "high"))
答案 1 :(得分:16)
我们可以使用.$
mtcars %>%
mutate(cg = case_when(.$carb <= 2 ~ "low", .$carb > 2 ~ "high")) %>%
.$cg %>%
table()
# high low
# 15 17
答案 2 :(得分:6)
感谢@sumedh:@hadley has explained这是TimeZone
的一个众所周知的缺点:
[]()
仍然有点实验,目前无效 在case_when
内。这将在未来版本中修复。
答案 3 :(得分:1)
就我而言,准引号很有帮助。您可以预先创建一组定义了变异规则的带引号的公式(可以使用第一个公式中的已知列名,也可以使用!!
并像第二个公式中那样动态创建规则),然后利用该公式在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
并在不同的地方使用它,将其应用于不同的数据集,而无需在每次需要复杂的突变时都手动键入所有规则。
作为该问题的最终答案,另外7个符号和两个括号解决了该问题
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
由reprex package(v0.2.1.9000)于2019-01-16创建
答案 4 :(得分:-2)
除了@ 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")
)
答案 5 :(得分:-2)
library(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"
)
)