web-dev-qa-db-fra.com

Remplacer une valeur dans un cadre de données basé sur une instruction conditionnelle (`if`)

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

110
KennyPeanuts

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)
190
diliop

un autre moyen utile de remplacer les valeurs

library(plyr)
junk$nm <- revalue(junk$nm, c("B"="b"))
37
Oriol Prat

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"
24
Marek

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")
19
Gavin Simpson

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"
11
user1021713

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
5
42-

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
# ...
1
loki
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")
0