[r] Replace given value in vector

I'm looking for a function which will replace all occurrences of one value with another value. For example I'd like to replace all zeros with ones. I don't want to have to store the result in a variable, but want to be able to use the vector anonymously as part of a larger expression.

I know how to write a suitable function myself:

> vrepl <- function(haystack, needle, replacement) {
+   haystack[haystack == needle] <- replacement
+   return(haystack)
+ }
> 
> vrepl(c(3, 2, 1, 0, 4, 0), 0, 1)
[1] 3 2 1 1 4 1

But I'm wondering whether there is some standard function to do this job, preferrably from the base package, as an alternative from some other commonly used package. I believe that using such a standard will likely make my code more readable, and I won't have to redefine that function wherever I need it.

This question is related to r replace

The answer is


A simple way to do this is using ifelse, which is vectorized. If the condition is satisfied, we use a replacement value, otherwise we use the original value.

v <- c(3, 2, 1, 0, 4, 0)
ifelse(v == 0, 1, v)

We can avoid a named variable by using a pipe.

c(3, 2, 1, 0, 4, 0) %>% ifelse(. == 0, 1, .)

A common task is to do multiple replacements. Instead of nested ifelse statements, we can use case_when from dplyr:

case_when(v == 0 ~ 1,
          v == 1 ~ 2,
          TRUE ~ v)

Old answer:

For factor or character vectors, we can use revalue from plyr:

> revalue(c("a", "b", "c"), c("b" = "B"))
[1] "a" "B" "c"

This has the advantage of only specifying the input vector once, so we can use a pipe like

x %>% revalue(c("b" = "B"))

To replace more than one number:

vec <- 1:10
replace(vec, vec== c(2,6), c(0,9)) #2 and 6 will be replaced by 0 and 9.

Edit:

for a continous series, you can do this vec <- c(1:10); replace(vec, vec %in% c(2,6), c(0,9)) but for vec <- c(1:10,2,2,2); replace(vec, vec %in% c(2,6), 0) we can replace multiple values with one value.


If you want to replace lot of values in single go, you can use 'library(car)'.

Example

library(car)

x <- rep(1:5,3)

xr <- recode(x, '3=1; 4=2')

x
## [1] 1 2 3 4 5 1 2 3 4 5 1 2 3 4 5
xr
## [1] 1 2 1 2 5 1 2 1 2 5 1 2 1 2 5

Another simpler option is to do:

 > x = c(1, 1, 2, 4, 5, 2, 1, 3, 2)
 > x[x==1] <- 0
 > x
 [1] 0 0 2 4 5 2 0 3 2

The ifelse function would be a quick and easy way to do this.


Why the fuss?

replace(haystack, haystack %in% needles, replacements)

Demo:

haystack <- c("q", "w", "e", "r", "t", "y")
needles <- c("q", "w")
replacements <- c("a", "z")

replace(haystack, haystack %in% needles, replacements)
#> [1] "a" "z" "e" "r" "t" "y"