Replace value in data frame based on conditional (`if`) operator in R

In the R data frame encoded below, I would like to replace all the times when B appears with B

 junk <- data.frame(x <- rep(LETTERS[1:4], 3), y <- letters[1:12]) colnames(junk) <- c("nm", "val") 

this provides:

  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 

My initial attempt was to use the for and if :

 for(i in junk$nm) if(i %in% "B") junk$nm <- "b" 

but as I am sure you can see, this replaces ALL junk$nm values ​​with B I can understand why this is done, but I can not get it to replace only those cases of garbage $ nm, where the original value was B

Thank.

NOTE. I managed to solve the problem with gsub , but in the interest of learning R, I would still like to know how to get my original approach to work (if possible)

+80
r
Apr 28 '11 at 19:53
source share
6 answers

It is easier to convert nm to characters and then make changes:

 junk$nm <- as.character(junk$nm) junk$nm[junk$nm == "B"] <- "b" 

EDIT: And if you really need to support nm as factors, add this to the end:

 junk$nm <- as.factor(junk$nm) 
+119
Apr 28 2018-11-21T00:
source share

another useful way to replace values

  library(plyr) revalue(junk$nm, c("B"="b")) 
+23
Dec 14 '13 at 16:27
source share

Short answer:

 junk$nm[junk$nm %in% "B"] <- "b" 

Take a look at Index vectors in the R Introduction (if you haven't read it yet).




EDIT. As noted in the comments, this solution works for character vectors, so you lose your data.

The best way for the factor is to change the level:

 levels(junk$nm)[levels(junk$nm)=="B"] <- "b" 
+17
Apr 28 2018-11-11T00:
source share

Since the data you show are factors, this makes things a bit more complicated. @diliop Answers a problem by converting a character variable to nm . To return to the initial factors, one more step is necessary.

An alternative is to manage factor levels in place.

 > lev <- with(junk, levels(nm)) > lev[lev == "B"] <- "b" > junk2 <- within(junk, levels(nm) <- lev) > junk2 nm val 1 A a 2 bb 3 C c 4 D d 5 A e 6 bf 7 C g 8 D h 9 A i 10 bj 11 C k 12 D l 

It's pretty simple, and I often forget that there is a replacement function for levels() .

Edit: As @Seth noted in the comments, this can be done in single-line mode without loss of clarity:

 within(junk, levels(nm)[levels(nm) == "B"] <- "b") 
+17
Apr 28 2018-11-21T00:
source share

The easiest way to do this in one command is to use the which command, and you also do not need to change factors to a character by doing this:

 junk$nm[which(junk$nm=="B")]<-"b" 
+9
Jan 07 2018-12-12T00:
source share

You created a factor variable in nm , so you need to either not do this or add an extra layer to the factor attributes. You should also avoid using <- in data.frame () arguments

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 
+4
April 2018-11-21T00:
source share



All Articles