Tim
Tim

Reputation: 3

R 3.1.2 - Paste metacharacters to use within a function

I am trying to write a function which lets me easily replace strings that begin with certain characters. I have written the following function, but R doesn't seem to recognize the metacharacters as soon I paste them to a string.

library(plyr)

vector <- c("cow", "chicken", "elephant", "garden", "banana")

map.start = function(vector, oldwords, newwords) {
  oldwords2 <- paste("^", oldwords, ".*", sep = "")
newvector <- mapvalues(vector, oldwords2, newwords)
return(newvector)
}

vector <- map.start(vector, "eleph", "donkey")
print(vector)

When executing these commands, the following error occurs: The following from values were not present in x: ^eleph.*

So, R does not seach for words beginning with 'eleph', but does not recognize the metacharacters and searches for an exact match of "^eleph.*", which does not exist of course. Can someone tell me if (and how) it is possible to combine metacharacters and strings within a function? Thanks!

edit: I tried using gsubfn for replacing multiple strings, but it doesn't seem to work. What am I still doing wrong?

library(gsubfn)

vector <- c("cow", "chicken", "elephant", "garden", "banana")

map.start = function(vector, oldwords, newwords) {
  oldwords2 <- paste("^", oldwords, ".*", sep = "")
  newvector <- gsubfn(oldwords2, newwords, vector)
  return(vector)
}

vector <- map.start(vector, c("eleph", "gard"), c("donkey", "ninja"))
print(vector)

Upvotes: 0

Views: 102

Answers (1)

Cath
Cath

Reputation: 24074

you can replace function mapvalues by function gsub from base R (which will work with regex):

map.start = function(vector, oldwords, newwords) {
    oldwords2 <- paste("^", oldwords, ".*", sep = "")
    newvector <- gsub(oldwords2, newwords, vector)
    return(newvector)
}

vector <- map.start(vector, "eleph", "donkey")
print(vector)
#[1] "cow"     "chicken" "donkey"  "garden"  "banana"

If you need to pass a vector of items and a vector of replacement, you can combine gsub with a for loop:

 map.start = function(vector, oldwords, newwords) {
        oldwords2 <- paste("^", oldwords, ".*", sep = "")
        for (i in 1:length(oldwords2)) {
           vector <- gsub(oldwords2[i], newwords[i], vector)
        }
        return(vector)
 }
 map.start(vector, c("eleph","chick"), c("donkey","duck"))
 #[1] "cow"     "duck" "donkey"  "garden"  "banana"

Another option without a for loop

 map.start = function(vector, oldwords, newwords) {
        oldwords2 <- paste("^", oldwords, ".*", sep = "")
        corresp <- do.call("rbind", mapply(function(x,y) cbind(ind=which(regexpr(x, vector)!=-1), new=y), 
                                           x=oldwords2, 
                                           y=newwords, 
                                           SIMPLIFY=F))
        vector[as.numeric(corresp[, "ind"])] <- corresp[, "new"]
        return(vector)
 }
 map.start(vector, c("eleph","chick"), c("donkey","duck"))
 #[1] "cow"     "duck" "donkey"  "garden"  "banana"

Upvotes: 1

Related Questions