5

I want to do multiple replacements in the matrix. For example,

x <-sample(1:20,50,rep=T)
replace(x, x == 4, 2)

Replacing the elements equal to 4 in x with 2 by using replace. But how can I replace x == 4 with 2, x ==3 with 4 and x == 5 with 6.

Is there any built function to replace (4,3,5) respectively with (2,4,6)?

Tunn
  • 1,506
  • 16
  • 25
user1784579
  • 83
  • 1
  • 7

3 Answers3

13

1) Try this:

 replace(seq(20), c(4,3,5), c(2,4,6))[x]

2) Here is a more general approach:

 c(2, 4, 6, x)[match(x, c(4, 3, 5, x))]

This second approach has the form: c(new, x)[match(x, c(old, x))]

Braiam
  • 1
  • 11
  • 47
  • 78
G. Grothendieck
  • 254,981
  • 17
  • 203
  • 341
7

I smell a data.table answer cooking but here's an environment lookup approach:

n <-50; set.seed(10)
x <-sample(1:20,50,rep=T) 

inputs <- c(4,3,5) 
outputs <- c(2,4,6)

library(qdap)
lookup(x, inputs, outputs, missing = NULL)

This one begged for a benchmark:

enter image description here

On 10,000 length vector (10 replications):

Unit: microseconds
      expr      min       lq     median        uq       max neval
  LOOKUP() 9875.384 9992.475 10236.9230 10571.405 11588.846    10
 REPLACE()   76.973   85.837    94.7005   104.031   111.961    10
    PLYR()  904.082  924.142   952.8315   973.124  1017.442    10
   MATCH() 1796.034 1825.423  1864.3760  1881.870  1902.396    10
Tyler Rinker
  • 108,132
  • 65
  • 322
  • 519
  • Thanks very much! The package qdap seems quite powerful! – user1784579 Apr 26 '13 at 03:38
  • +1 for the benchmarking!! We all love a benchmark! Especially with a chart. :-) – Simon O'Hanlon Apr 26 '13 at 08:40
  • I don't really understand how the other solutions work for the given input and your qdap::lookup errors out, complaining about java, but... modifying in place with data.table is fairly fast: `setDT(list(x))[ .(inputs, outputs), V1 := V2, on="V1"]` (`x` itself is modified, so no need to assign the result somewhere... this makes benchmarking annoying, though.) `input` and `output` have to be integer vectors for this to work. Landed here after seeking better approaches to http://stackoverflow.com/q/37309423/ – Frank May 18 '16 at 21:34
  • @Frank Java makes no sense as I don't use it in `lookup` as I use `data.table` in the backend. Before that I used an environment as a hash table so it should have never had a java message attached to it. Also there is not `qdap::lookup`. It was placed in it's own package **qdapTools** ions ago. As far as I know nothing beats data.table for these sorts of lookup tasks except maybe a vector lookup on shorter vectors. This question is from over 2 years ago so I'd say it's not really relevant any more. – Tyler Rinker May 20 '16 at 01:41
  • Bottom line if you like data.table and are comfortable with it go that route because that's what you're getting with `qdapTools::lookup` anyway. ps just tried this code in my answer above and get no error. – Tyler Rinker May 20 '16 at 01:41
  • Thanks for the details. My bad on "qdap::lookup"; I'm not very package-savvy. And now that I try it on my home computer, I also get no error. I'm blaming my IT dept. I can understand if you're bothered by getting comments on old posts, but two years isn't so old; and it's not as if SO is built to support/encourage new duplicate questions just because their dupes are old or something. – Frank May 20 '16 at 02:33
  • 1
    @Frank wasn't bothered at all... sorry if it seemed that way. Wanted to let others know I feel strongly about the data.table lookup as superseding anything here. – Tyler Rinker May 20 '16 at 12:48
6

You can do this:

find    <- c(4,3,5)
replace <- c(2,4,6)
found   <- match(x, find)

ifelse(is.na(found), x, replace[found])

or use plyr's mapvalues which uses a similar implementation using match:

library(plyr)
mapvalues(x, find, replace, warn.missing = FALSE)

Both methods work with any kind of data. For character vectors, you could also convert into factors and permute levels.

flodel
  • 87,577
  • 21
  • 185
  • 223
  • Thanks! The first method seems slower than the second one. I have just found the poser of plyr! – user1784579 Apr 26 '13 at 04:17
  • (+1) personally I would do it this way. – Nishanth Apr 26 '13 at 04:19
  • 1
    (+1) I think this is the simplest solution. It might be nice though not to use `replace` and `find` as the vector names given that they are both base functions - one of which is directly related to the task at hand. I know I frequently got confused reading questions with this issue when I started learning R. – thelatemail Apr 26 '13 at 04:59