Take the 2-minute tour ×

This is a my data (A).

[1] shoes
[2] childrenshoes
[3] nikeshoes
[4] sportsshiirts
[5] nikeshirts
[6] shirts

Also, that is another data (B). It is a reference data.

   keyword  value
[1] shoes    1
[2] shirts   2

I need to match this dataset.

So, I want to that results.

    keyword        vlaue
[1] shoes          1
[2] childrenshoes  1     (because, this keyword include the 'shoes')
[3] nikeshoes      1     (because, this keyword include the 'shoes')
[4] sportsshiirts  2     (because, this keyword include the 'shirts')
[5] nikeshirts     2     (because, this keyword include the 'shirts')
[6] shirts         2

If I utilize the 'merge', I colud not match this dataset. This is because keywords in data(B) is not perfectly match with data in data(A).

I can handle this one by one by using regexpr() or gregexpr(). However, I have a lot of refernece in data (B)

So, How can I handle this problem?

share|improve this question
Interesting question. Do be sure that in the future, you share your example data in a way that is easy for others on the site to copy-and-paste before experimenting. –  Ananda Mahto Jan 30 '13 at 7:28
add comment

1 Answer

up vote 6 down vote accepted

Here's one approach:

First, your data:

temp <- c("shoes", "childrenshoes", "nikeshoes", 
          "sportsshiirts", "nikeshirts", "shirts")

matchme <- structure(list(keyword = c("shoes", "shirts"), value = 1:2), 
                     .Names = c("keyword", "value"), 
                     class = "data.frame", row.names = c(NA, -2L))

Second, the output, all in one go:

  keyword = temp, 
  value = rowSums(sapply(seq_along(matchme[[1]]), function(x) {
    temp[grepl(matchme[x, 1], temp)] <- matchme[x, 2]
  }), na.rm = TRUE))
#         keyword value
# 1         shoes     1
# 2 childrenshoes     1
# 3     nikeshoes     1
# 4 sportsshiirts     0
# 5    nikeshirts     2
# 6        shirts     2

grepl performs logical matching of each element in your "matchme" data.frame against your source "temp" data.frame. If a match is found, it extracts the value from the "value" column of the "matchme" data.frame. Otherwise, it keeps the original value. That's fine, because we know that when we convert the resulting vector using as.numeric, anything that can't be coerced to a number will become NA.

In the sapply step, you'll get a matrix. If we can assume that there will only ever be one match per item, then we can safely use rowSums with the argument na.rm = TRUE to "collapse" that matrix into a single vector that can be combined with our "temp" data to create the resulting data.frame.

I've added a suppressWarnings in there because I know that I will get lots of NAs introduced by coercion warnings that don't tell me anything I don't already know.

Note the 0 for "sportsshiirts". If you need approximate matching, you might want to look into agrep and see if you can modify this approach.

share|improve this answer
Thank you for your help! –  kmangyo Jan 30 '13 at 11:31
add comment

Your Answer


