繁体   English   中英

在 dplyr 的 mutate 中使用 switch 语句

[英]Using switch statement within dplyr's mutate

我想在 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 的值不是单一的,例如:

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中的 case_when 并且我对使用它不感兴趣,我只对使switch在 mutate 中工作感兴趣
  • 理想的解决方案将允许进一​​步扩展以将mutate_at与作为传递的变量一起使用.

switch未矢量化,因此为了提高效率,您需要使用ifelsecase_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))
}

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

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)]
              )

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM