2017-10-18 14 views
0

Je voudrais utiliser une instruction switch dans mute de dplyr. J'ai une fonction simple qui effectue certaines opérations et attribue des valeurs alternatives via le commutateur, par exemple:Utilisation de l'instruction switch dans la mute de dplyr

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

Cela fonctionne comme désiré lorsqu'elle était appliquée à scalaires:

>> convert_am(1) 
[1] TRUE 
>> convert_am(2) 
[1] NA 
>> convert_am(0) 
[1] FALSE 

je voudrais arriver à des résultats équivalents via mutate appel:

mtcars %>% mutate(am = convert_am(am)) 

Cela échoue:

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

Je comprends que ce soit parce que les valeurs transmises à changer ar pas seul, comme dans l'exemple:

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

Vectorisation

Tentative de vectoriser également d'obtenir les résultats souhaités:

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 

Notes

  • Je suis au courant de case_when dans dplyr et je ne suis pas intéressé à l'utiliser, je suis seulement intéressé à faire switch travail à l'intérieur muter
  • solution idéale permettrait d'expansion d'utiliser mutate_at avec des variables passées en .
+1

Je pense que vous devez vectoriser 'convert_am' au lieu de' fun_switch'? Essayez par exemple 'mtcars%>% mute (am = Vectorize (convert_am) (am))'. Ce que vous avez fait là retourne une fonction 'vf' (voir'? Vectorize') – konvas

+0

@konvas Juste point, n'hésitez pas à poster une solution de travail. C'est plus amusant que tout, je pense qu'avec tous les wrappers, beaucoup d'efficacité dérivée de la commutation des choses sera perdue, mais je veux l'avoir fait juste pour avoir un exemple de travail. – Konrad

+1

En effet, ce n'est pas du tout efficace, vous pouvez aussi bien utiliser 'do' et non vectoriser du tout. J'essaierais d'utiliser 'case_when' puisque c'est pour ça, mais supposons que tu as tes raisons pour ne pas vouloir l'utiliser :) – konvas

Répondre

3

switch non vectorisé donc pour l'efficacité, vous devez utiliser ifelse ou case_when - mais votre question est précisément de switch, vous pouvez obtenir ce que vous voulez par vectorisation, par exemple

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

ou

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

Ils sont à la fois inefficaces car ils impliquent une boucle sous le capot.