15

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]
}
zx8754
  • 52,746
  • 12
  • 114
  • 209
Roman Luštrik
  • 69,533
  • 24
  • 154
  • 197

2 Answers2

19

Try with match

y[match(x, x.lvl)]
Marek
  • 49,472
  • 15
  • 99
  • 121
  • You don't need match. just use y[x] –  Jul 21 '11 at 02:19
  • 5
    @Mahbub In this case yes but generally you need match (e.g. if `x` is vector of letters). Check comments below VitoshKa answer. – Marek Jul 21 '11 at 19:42
9

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
  • 8,387
  • 3
  • 35
  • 59
  • 2
    In the toy example you could even use y[x] – Joris Meys Oct 11 '10 at 10:31
  • Perfect. It works even without converting to a factor and detects if x has more "levels" than foreseen by y. – Roman Luštrik Oct 11 '10 at 11:18
  • 2
    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 Oct 11 '10 at 11:54
  • 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 Oct 11 '10 at 12:12