tags:

views:

76

answers:

2

I would like to replace values in a vector (x) with values from another vector (y). Catch 22: The methods needs to be dynamic to accommodate different number of "levels" in vector x. For instance, consider vector x

x <- sample(c(1, 2, 3, 4, 5), 100, replace = TRUE)
> x
  [1] 2 4 1 1 3 1 1 1 1 1 2 2 5 5 4 5 5 3 4 1 2 2 3 3 3 5 1 3 4 5 5 3 2 4 3 1 3
 [38] 1 4 5 4 1 4 5 4 5 2 4 2 5 3 4 3 1 2 1 1 5 1 4 2 2 5 2 2 4 5 2 4 5 2 5 4 1
 [75] 3 3 4 4 1 1 4 4 2 4 5 4 5 5 4 2 5 2 4 5 3 2 1 1 2 2

where I would like to replace 1s with 100, 2s with 200 and so on.

This can be done easily with a for loop but for large vectors, several 100 thousand values, this is highly inefficient. Any tips how to optimize the code?

x <- sample(c(1, 2, 3, 4, 5), 100, replace = TRUE)
y <- c(100, 200, 300, 400, 500)
x.lvl <- c(1, 2, 3, 4, 5)
x.temp <- x

for (i in 1:length(y)) {
    x.temp[which(x == x.lvl[i])] <- y[i]
}
+1  A: 

Working with factors might be faster:

xf <- as.factor(x)
y[xf]

Note, that levels(xf) gives you a character vector similar to your x.lvl. Thus, for this method to work, elements of y should correspond to appropriate elements of levels(xf).

VitoshKa
In the toy example you could even use y[x]
Joris Meys
Or, just x*100 :)
VitoshKa
Perfect. It works even without converting to a factor and detects if x has more "levels" than foreseen by y.
Roman Luštrik
Using match, as Marek proposed is a general way to do it, and does not require conversion to a factor. It's just lucky coincidence that your x vector contains only numbers from 1 to N and so you can use positional matching as in y[x].
VitoshKa
Perhaps I should be explicit that this way works for my needs, which may not be the case for others. Thank you for this warning. Marek, can you amend your post and mention the generality of your approach?
Roman Luštrik
+4  A: 

Try with match

y[match(x, x.lvl)]
Marek