1
votes

grepl in R: Remplacer les niveaux de caractères / numériques

J'aime remplacer mes niveaux dog1 ... dog4 et cat1 ... cat4 par seulement deux niveaux DOG et CAT, mais si j'utilise grepl, ma sortie n'est que NA.

Dans mon code:

head(d)

     x                 y
1 DOG  0.906357739138289
2 DOG  0.974674552504268
3 DOG  0.664045049199848
4 DOG  0.911777985232099
5 CAT  0.246575548162824
6 CAT  0.758069789161901

Message d'avertissement: Dans [ ( * tmp * , grepl ("dog", d $ x), value = c (NA, NA, NA,: niveau de facteur non valide, NA généré

d$x[grepl("cat", d$x)] <- "CAT"

Warning message:
In `[<-.factor`(`*tmp*`, grepl("cat", d$x), value = c(NA_integer_,  :
  invalid factor level, NA generated

head(d)

     x                 y
1 <NA> 0.906357739138289
2 <NA> 0.974674552504268
3 <NA> 0.664045049199848
4 <NA> 0.911777985232099
5 <NA> 0.246575548162824
6 <NA> 0.758069789161901

Ma sortie souhaitable si le code fonctionne correctement est:

x  <- (rep(c("dog1","dog2","dog3","dog4","cat1","cat2","cat3","cat4"),2)) #Levels
y<-rnorm(16)
d<-data.frame(cbind(x,y))
head(d)

     x                 y
1 dog1 0.906357739138289
2 dog2 0.974674552504268
3 dog3 0.664045049199848
4 dog4 0.911777985232099
5 cat1 0.246575548162824
6 cat2 0.758069789161901


d$x[grepl("dog", d$x)] <- "DOG" 


0 commentaires

3 Réponses :


2
votes

Vous pouvez essayer de créer le bloc de données avec des chaînes comme facteurs faux:

d <- data.frame(cbind(x,y), stringsAsFactors=FALSE)
d$x[grepl("dog", d$x)] <- "DOG"
d$x[grepl("cat", d$x)] <- "CAT" 


0 commentaires

1
votes

La clé ici (comme Tim l'a laissé entendre) est de comprendre comment les variables factor , bien que similaires en surface, sont en réalité complètement différentes des variables character .

Voici une façon d'accéder et de mettre à jour les niveaux de votre facteur:

levels(d$x)
# [1] "cat1" "cat2" "cat3" "cat4" "dog1" "dog2" "dog3" "dog4"

levels(d$x)[grepl("dog", levels(d$x))] <- "DOG"
levels(d$x)[grepl("cat", levels(d$x))] <- "CAT"
head(d)
#     x                   y
# 1 DOG -0.0489713202962167
# 2 DOG  -0.548503649991368
# 3 DOG   0.460493884654479
# 4 DOG   0.143044665735075
# 5 CAT   -2.13008189672678
# 6 CAT  -0.136767747543626

levels(d$x)
[1] "CAT" "DOG"


0 commentaires

0
votes

Encore une autre version mais utilisant regex ici. Nous capturons tout jusqu'à ce qu'un chiffre soit trouvé et le transformons en majuscules. ( \\ U ).

d$x <- sub("(.*)\\d+", "\\U\\1", d$x, perl = TRUE)
d$x
 #[1] "DOG" "DOG" "DOG" "DOG" "CAT" "CAT" "CAT" "CAT" "DOG" "DOG" "DOG" "DOG" 
 #    "CAT" "CAT" "CAT" "CAT"


0 commentaires