Reputation: 43
I have this vector b <- c(1, 2, 2, 1, 2, 1, 1, 2, 2, 1)
and I need to replace all 1s into 2s and all 2s into 1s.
I have tried the replace option as well as the b==1 <- 2
but it needs to be at the same time to work.
How
Upvotes: 1
Views: 91
Reputation: 34703
A bunch of different ways to do this. Not sure why you want to do it simultaneously...
But if you absolutely are obsessed with that, how about:
b <- ifelse(b == 1, 2, 1)
Or you could write a simple swap function:
swap <- function(x){
if(length(us <- unique(x)) > 2L) stop("this function is too naive for this vector")
out <- vector(class(x), length(x))
out[x == us[1L]] <- us[2L]
out[x == us[2L]] <- us[1L]
out
}
Jota adds the lookup table approach
b <- c("1" = 2, "2" = 1)[b]
A similar version is to use factor
s:
b <- factor(b, levels = c("1" = 2, "2" = 1))
(this looks like it didn't work, until you look at as.integer(b)
)
That should work more generally too, e.g. b <- c(1, 1, 2, 2, 2, 3); c("1" = 3, "2" = 1, "3" = 2)[b]
, but if that seems a bit hard to wrap your head around the best way may be to just go step-by-step:
idx <- which(b == 1)
b[idx] <- 2
b[-idx] <- 1
One more way (inspired by nicola's answer below) is:
b <- (idx <- b == 1)*2 + !idx
Upvotes: 6
Reputation: 24480
Just use simple math. If b
is made only of 1s and 2s, just try:
3-b
#[1] 2 1 1 2 1 2 2 1 1 2
More generally, you can try:
(b==1)*2+(b==2)+b*(!b %in% 1:2)
For instance:
set.seed(1)
b<-sample(10)
b
#[1] 3 4 5 7 2 8 9 6 10 1
(b==1)*2+(b==2)+b*(!b %in% 1:2)
#[1] 3 4 5 7 1 8 9 6 10 2
Upvotes: 3