在dplyr的mutate中使用switch语句

Kon*_*rad 2 r switch-statement dplyr mutate

我想在dplyr的mutate中使用switch语句。我有一个简单的函数,可以执行一些操作并通过switch分配备用值,例如:

convert_am <- function(x) {
    x <- as.character(x)
    switch(x,
           "0" = FALSE,
           "1" = TRUE,
           NA)
}
Run Code Online (Sandbox Code Playgroud)

当应用于标量时,这可以按需要工作:

>> convert_am(1)
[1] TRUE
>> convert_am(2)
[1] NA
>> convert_am(0)
[1] FALSE
Run Code Online (Sandbox Code Playgroud)

我想通过mutate致电获得相同的结果:

mtcars %>% mutate(am = convert_am(am))
Run Code Online (Sandbox Code Playgroud)

这将失败:

错误mutate_impl(.data, dots):评估错误:EXPR必须是长度为1的向量。

我了解这是因为传递给switch ar的值不是单一的,例如:

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
Run Code Online (Sandbox Code Playgroud)

笔记

  • 我知道case_when在dplyr中,我对使用它不感兴趣,仅对switch在mutate 中进行工作感兴趣
  • 理想的解决方案将允许进一​​步扩展以mutate_at与传递为.

kon*_*vas 5

switch不是向量化的,因此为了提高效率,您需要使用- ifelsecase_when-因为您的问题专门关于switch,您可以通过向量化来实现所需的功能,例如

convert_am <- Vectorize(function(x) {
    x <- as.character(x)
    switch(x,
       "0" = FALSE,
       "1" = TRUE,
       NA)
})
Run Code Online (Sandbox Code Playgroud)

要么

convert_am <- function(x) {
    x <- as.character(x)
    sapply(x, function(xx) switch(xx,
       "0" = FALSE,
       "1" = TRUE,
       NA))
}
Run Code Online (Sandbox Code Playgroud)

它们都效率低下,因为它们涉及引擎盖下的循环。