Dans la trame de données R codée ci-dessous, je voudrais remplacer toutes les fois où B
apparaît avec b
.
junk <- data.frame(x <- rep(LETTERS[1:4], 3), y <- letters[1:12])
colnames(junk) <- c("nm", "val")
cela fournit:
nm val
1 A a
2 B b
3 C c
4 D d
5 A e
6 B f
7 C g
8 D h
9 A i
10 B j
11 C k
12 D l
Ma tentative initiale consistait à utiliser une instruction for
et if
comme suit:
for(i in junk$nm) if(i %in% "B") junk$nm <- "b"
mais comme je suis sûr que vous pouvez le voir, cela remplace TOUTES les valeurs de junk$nm
par b
. Je peux voir pourquoi cela se produit mais je n'arrive pas à le faire pour remplacer uniquement les cas de fichiers inutiles $ nm où la valeur d'origine était B
.
NOTE: J'ai réussi à résoudre le problème avec gsub
mais, dans l’intérêt d’apprendre R, j’aimerais toujours savoir comment obtenir mon approche initiale au travail (si cela est possible).
Plus facile de convertir nm en caractères, puis d'effectuer le changement:
junk$nm <- as.character(junk$nm)
junk$nm[junk$nm == "B"] <- "b"
EDIT: Et si vous avez effectivement besoin de conserver nm comme facteur, ajoutez ceci à la fin:
junk$nm <- as.factor(junk$nm)
un autre moyen utile de remplacer les valeurs
library(plyr)
junk$nm <- revalue(junk$nm, c("B"="b"))
La réponse courte est:
junk$nm[junk$nm %in% "B"] <- "b"
Jetez un oeil à vecteurs d'index dans R Introduction (si vous ne le lisez pas encore).
MODIFIER. Comme noté dans les commentaires, cette solution fonctionne pour les vecteurs de caractères, alors échouez dans vos données.
Pour facteur le meilleur moyen est de changer de niveau:
levels(junk$nm)[levels(junk$nm)=="B"] <- "b"
Comme les données que vous montrez sont des facteurs, cela complique un peu les choses. La réponse de @ diliop résout le problème en convertissant en nm
en une variable de caractère. Pour revenir aux facteurs d'origine, une étape supplémentaire est nécessaire.
Une alternative consiste à manipuler les niveaux du facteur en place.
> lev <- with(junk, levels(nm))
> lev[lev == "B"] <- "b"
> junk2 <- within(junk, levels(nm) <- lev)
> junk2
nm val
1 A a
2 b b
3 C c
4 D d
5 A e
6 b f
7 C g
8 D h
9 A i
10 b j
11 C k
12 D l
C’est assez simple et j’oublie souvent qu’il existe une fonction de remplacement pour levels()
.
Edit: Comme l'a noté @Seth dans les commentaires, cela peut être fait en une ligne, sans perte de clarté:
within(junk, levels(nm)[levels(nm) == "B"] <- "b")
Le moyen le plus simple de procéder dans une commande consiste à utiliser la commande which
et à ne pas modifier les facteurs en caractères en procédant comme suit:
junk$nm[which(junk$nm=="B")]<-"b"
Vous avez créé une variable de facteur dans nm
, vous devez donc éviter de le faire ou ajouter un niveau supplémentaire aux attributs de facteur. Vous devez également éviter d'utiliser <-
dans les arguments de data.frame ()
Option 1:
junk <- data.frame(x = rep(LETTERS[1:4], 3), y =letters[1:12], stringsAsFactors=FALSE)
junk$nm[junk$nm == "B"] <- "b"
Option 2:
levels(junk$nm) <- c(levels(junk$nm), "b")
junk$nm[junk$nm == "B"] <- "b"
junk
Si vous travaillez avec des variables de caractère (notez que stringsAsFactors
est false ici), vous pouvez utiliser replace:
junk <- data.frame(x <- rep(LETTERS[1:4], 3), y <- letters[1:12], stringsAsFactors = FALSE)
colnames(junk) <- c("nm", "val")
junk$nm <- replace(junk$nm, junk$nm == "B", "b")
junk
# nm val
# 1 A a
# 2 b b
# 3 C c
# 4 D d
# ...
stata.replace<-function(data,replacevar,replacevalue,ifs) {
ifs=parse(text=ifs)
yy=as.numeric(eval(ifs,data,parent.frame()))
x=sum(yy)
data=cbind(data,yy)
data[yy==1,replacevar]=replacevalue
message=noquote(paste0(x, " replacement are made"))
print(message)
return(data[,1:(ncol(data)-1)])
}
Appelez cette fonction en utilisant la ligne ci-dessous.
d=stata.replace(d,"under20",1,"age<20")