我想在dplyr的mutate中使用switch语句。我有一个简单的函数,它执行一些操作并通过switch指定替代值,例如:
convert_am <- function(x) {
x <- as.character(x)
switch(x,
"0" = FALSE,
"1" = TRUE,
NA)
}
当应用于标量时,这可以正常工作:
>> convert_am(1)
[1] TRUE
>> convert_am(2)
[1] NA
>> convert_am(0)
[1] FALSE
我希望通过mutate
调用来获得相同的结果:
mtcars %>% mutate(am = convert_am(am))
这失败了:
mutate_impl(.data, dots)
出错:评估错误:EXPR必须 是长度为1的向量。
据我所知,这是因为传递给switch ar的值不是单一的,例如:
{p>convert_am(c(1,2,2))
switch(x, 0 = FALSE, 1 = TRUE, NA)
出错:EXPR必须是长度为1的向量
尝试矢量化也会产生预期的结果:
convert_am <- function(x) {
x <- as.character(x)
fun_switch <- function(x) {
switch(x,
"0" = FALSE,
"1" = TRUE,
NA)
}
vf <- Vectorize(fun_switch, "x")
}
>> mtcars %>% mutate(am = convert_am(am))
Error in mutate_impl(.data, dots) :
Column `am` is of unsupported type function
case_when
并且我对使用它不感兴趣,我只对使switch
在mutate中工作感兴趣mutate_at
.
答案 0 :(得分:5)
switch
未进行矢量化,因此为了提高效率,您需要使用ifelse
或case_when
- 但由于您的问题特别针对switch
,因此您可以实现所需的效果矢量化,例如
convert_am <- Vectorize(function(x) {
x <- as.character(x)
switch(x,
"0" = FALSE,
"1" = TRUE,
NA)
})
或
convert_am <- function(x) {
x <- as.character(x)
sapply(x, function(xx) switch(xx,
"0" = FALSE,
"1" = TRUE,
NA))
}
它们效率低下,因为它们涉及到引擎盖下的循环。
答案 1 :(得分:1)
This is simple enough to handle with ifelse directly:
Test <- tibble::tibble(
am = c(-1:5,NA,1, 0)
)
Test %>%
mutate(
newam = ifelse(am == 1, TRUE,
ifelse(am == 0, FALSE, NA))
)
With more categories, use a named vector:
Test %>%
mutate(
newam = ifelse(is.na(am) | !am %in% c(1,3,5), NA,
c("1" = "in1", "3" = "in3", "5" = "in5")[as.character(am)])
)
In fact if the value is not in the named list it will default to an NA
I think this will be pretty efficient
Test %>%
mutate(
newam = c("1" = "in1", "3" = "in3", "5" = "in5")[as.character(am)]
)