Reputation: 3
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
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