lore
lore

Reputation: 43

How to changes values into one another in a vector smultaneously?

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

Answers (3)

MichaelChirico
MichaelChirico

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 factors:

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

nicola
nicola

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

boshek
boshek

Reputation: 4406

You could do something like this:

ifelse(b==1,2,1)

Upvotes: 3

Related Questions