Cela devrait être assez simple, mais même après avoir vérifié toute la documentation et les exemples en ligne, je ne l’ai pas.
J'aimerais utiliser switch () pour remplacer les valeurs d'un vecteur de caractères.
Un exemple factice, extrêmement simple et reproductible:
test<-c("He is", "She has", "He has", "She is")
Supposons que je veuille attribuer "1" aux phrases incluant le verbe "être" et "2" aux phrases comprenant le verbe "avoir". Ce qui suit ne fonctionne pas:
test<-switch(test,
"He is"=1,
"She is"=1,
"He has"=2,
"She has"=2)
Message d'erreur:
+ + + + Error in switch(test, `He is` = 1, `She is` = 1, `He has` = 2, `She has` = 2) :
EXPR must be a length 1 vector
Je pense que EXPR est en effet un vecteur de longueur 1, alors qu'est-ce qui ne va pas?
Je pensais que peut-être R attendait des caractères comme remplaçants, mais ni le wrapping switch () dans un "as.integer" ni le travail suivant:
test<-switch(test,
"He is"="1",
"She is"="1",
"He has"="2",
"She has"="2")
Peut-être que ça ne vectorise pas et que je devrais faire une boucle? Est-ce que c'est ça? Serait décevant, compte tenu de la force de R est la vectorisation. Merci d'avance!
La forme vectorisée de if
est ifelse
:
test <- ifelse(test == "He is", 1,
ifelse(test == "She is", 1,
ifelse(test == "He has", 2,
2)))
ou
test <- ifelse(test %in% c("He is", "She is"), 1, 2)
switch
est fondamentalement une façon d'écrire des tests imbriqués if
-else
. Pensez à if
et switch
en tant que flux de contrôle instructions, et non en tant qu'opérateurs de transformation de données. Vous les utilisez pour contrôler l'exécution d'un algorithme, par exemple pour tester la convergence ou pour choisir le chemin d'exécution à suivre. Vous ne les utiliseriez pas pour manipuler directement des données dans la plupart des cas.
Voici la bonne façon de vectoriser une fonction, par ex. commutateur :
# Data vector:
test<-c("He is", "She has", "He has", "She is")
# Vectorized SWITCH:
foo <- Vectorize(function(a) {
switch(as.character(a),
"He is" = 1,
"She is" = 1,
"He has" = 2,
2)
}, "a")
# Result:
foo(test)
He is She has He has She is
1 2 2 1
J'espère que ça aide.
Tu pourrais essayer
test_out <- sapply(1:length(test), function(x) switch(test[x],
"He is"=1,
"She is"=1,
"He has"=2,
"She has"=2))
Ou équivalent
test_out <- sapply(test, switch,
"He is"=1,
"She is"=1,
"He has"=2,
"She has"=2)
J'ai trouvé cette approche la plus lisible:
# input
test <-c("He is", "She has", "He has", "She is", "Unknown", "She is")
# mapping
map <- c(
"He is" = 1,
"She has" = 2,
"He has" = 2,
"She is" = 1)
answer <- map[test]
# output
answer
He is She has He has She is <NA> She is
1 2 2 1 NA 1
Si test
est numérique, vous devez convertir la valeur en character
pour pouvoir utiliser ceci.
"Vectoriser" est basé sur la fonction "mapply", alors que "ifelse" est une fonction de base qui devrait déjà être vectorisée. Donc, en termes de performances, "Vectoriser" peut être plus lent. Il est facile de vectoriser une fonction R avec la famille "apply", mais les performances posent généralement problème pour les gros volumes. Mieux vaut utiliser des fonctions de base optimisées pour travailler avec des vecteurs.
Bien que je préfère généralement les approches de base R, il existe un package avec une fonction de commutateur vectorisé.
library(broman)
switchv(c("horse", "fish", "cat", "bug"),
horse="fast",
cat="cute",
"what?")
Ajouté basé sur le commentaire pour utiliser les données OP.
library(broman)
test<-c("He is", "She has", "He has", "She is")
test<-switchv(test,
"He is"="1",
"She is"="1",
"He has"="2",
"She has"="2")
test
Voici une solution avec recode()
de car
:
# Data vector:
x <- c("He is", "She has", "He has", "She is")
library("car")
recode(x, "'He is'=1; 'She is'=1; 'He has'=2; 'She has'=2") # or
recode(x, "c('He is', 'She is')=1; c('He has', 'She has')=2")