bmciv
bmciv

Reputation: 144

R Conditionally Alter String

This seems like a simple question, but I have not been able to successfully google it. I have two vectors of strings that I would like to combine based on a 3rd vector of TRUE FALSE.

Example:

strvec1 <- c("str1", "str2", "str3")
strvec2 <- c("alt1", "alt2", "alt3")
boolvec <- c(FALSE, FALSE, TRUE)

I would like for to call somefunction(strvec1, strvec2, boolvec) and for the result to be c("str1", "str2", "alt3").

Thank you for the help.

Upvotes: 2

Views: 55

Answers (3)

talat
talat

Reputation: 70256

If the strvectors are the same length, you can do:

cbind(strvec1, strvec2)[cbind(seq_along(strvec1), boolvec+1)]
# [1] "str1" "str2" "alt3"

And in a function:

f <- function(x,y,z) cbind(x, y)[cbind(seq_along(x), z+1L)]
f(strvec1, strvec2, boolvec)
# [1] "str1" "str2" "alt3"

Another option would be replace:

f2 <- function(x, y, z) replace(x, which(z), y[z])
f2(strvec1, strvec2, boolvec)
# [1] "str1" "str2" "alt3"

Here's a little comparison - only as rough indication:

strvec1 <- sample(letters, 1e6, T)
strvec2 <- sample(letters, 1e6, T)
boolvec <- sample(c(TRUE, FALSE), 1e6, T)
somefunction <- function(x, y, z) ifelse(z, y, x)
f <- function(x,y,z) cbind(x, y)[cbind(seq_along(x), z+1L)]
system.time(somefunction(strvec1, strvec2, boolvec))
#       User      System     elapsed 
#      0.494       0.025       0.519 
system.time(f(strvec1, strvec2, boolvec))
#       User      System     elapsed 
#      0.048       0.008       0.056 
system.time(f2(strvec1, strvec2, boolvec))
#       User      System     elapsed 
#      0.048       0.002       0.050 

Upvotes: 1

pete
pete

Reputation: 2396

The somefunction you want is ifelse:

strvec1 <- c("str1", "str2", "str3")
strvec2 <- c("alt1", "alt2", "alt3")
boolvec <- c(FALSE, FALSE, TRUE)

ifelse(boolvec, strvec2, strvec1)
# [1] "str1" "str2" "alt3"

NB: Note the order of strvec1 and strvec2. TRUE maps to the second (if) argument and FALSE maps to the third (else) argument.

Upvotes: 1

David Arenburg
David Arenburg

Reputation: 92282

Another option would be just

somefunction <- function(x, y, z) ifelse(z, y, x)

somefunction(strvec1, strvec2, boolvec)
## [1] "str1" "str2" "alt3"

Upvotes: 2

Related Questions