2017-10-18 137 views
0

我想在dplyr的mutate中使用switch语句。我有一个简单的函数,执行某些操作,并且经由开关分配的替代值,例如:在dplyr的mutate中使用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)) 

这种失败:

Error in mutate_impl(.data, dots) : Evaluation error: EXPR must be a length 1 vector.

我明白,这是因为传递到切换值AR不是单一的,如实施例中:

convert_am(c(1,2,2)) Error in switch(x, 0 = FALSE, 1 = TRUE, NA) : EXPR must be a length 1 vector

矢量

尝试也向量化得到所需的结果:

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 

备注

  • 我知道在dplyr case_when,我没有兴趣使用它,我只是在做发生变异
  • 的理想解决方案里面switch工作将允许进一​​步扩展使用mutate_at与作为.传递的变量感兴趣
+1

我认为你需要Vectorize'convert_am'而不是'fun_switch'?试试例如'mtcars%>%mutate(am = Vectorize(convert_am)(am))'。你在那里做了什么返回一个'vf'函数(参见'Vectorize') – konvas

+0

@konvas公平点,随时发布工作解决方案。它比任何东西都更有趣,我认为,所有的包装都会因为切换东西而产生很多效率,但我希望能够完成一个有效的例子。 – Konrad

+1

事实上,这根本没有效率,你可以使用'do'而不是矢量化。我会尝试使用'case_when',因为这就是它的存在,但假设你有你不想使用它的原因:) – konvas

回答

3

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

他们都是低效的,因为它们涉及的引擎盖下一个循环。