DD chen
DD chen

Reputation: 189

Match names with R for each element of dataframe

I have 2 data frames:

data1 <- data.frame(names = c("ALBERT | ALBERTIS 2", 
                              "PIERRE | JEAN | ALBERT", 
                              "ALBERTOS"))
data2 <- data.frame(names_search = c("ALBERT", "PIERRE"))

I want to know that each whole WORD of data2 is present in data1. A new column in data1 will contain those elements matched. So I want a result like:

data3 <- data.frame(names = c("ALBERT | ALBERTOS | ALBERT 2", 
                              "ALBERT | ALBERTOS | ALBE 2",
                              "PIERRE | PIERRE 2 | PIERRE_SECOND | PIERRE_SECOND 2"), 
                    names_search = c("ALBERT", "ALBERT | PIERRE", ""))

Do you have any idea how to do this?

I tried this in double loop (hope you can give a better way) but it failed.

for( i in 1:nrow(data1)){
  result <- ""
  for(j in 1: nrow(data2)){
     present <- grepl(eval(parse(text = paste0('\\<',data2$names_search[j],'\\>'))), data1$names[i], fixed = T)
     # I check if the whole word data[j] is present in data1[i]

     if(present ==T){
       result <- paste(result, data2$names_search[j], sep= "|")

     }


  }
  data1$names_search[i] <- result

}

Upvotes: 2

Views: 39

Answers (1)

jay.sf
jay.sf

Reputation: 72828

We can split the strings (i.e. each line) at " | " using strsplit; thereafter we just subset each iteration with the match vector of data2 if it's %in%side. At the end, the if handles the case when there is no match, the else pastes the result into the desired form.

data1 <- transform(
  data1, 
  names_search=sapply(strsplit(as.character(data1$names), " | ", fixed=TRUE), function(x) {
    out <- x[x %in% data2$names_search]
    if (length(out) == 0) NA_character_
    else paste(out, collapse=" | ")
  }))

Result

data1
#                    names names_search
# 1    ALBERT | ALBERTIS 2   ALBERTIS 2
# 2 PIERRE | JEAN | ALBERT       PIERRE
# 3               ALBERTOS         <NA>

Data

data1 <- structure(list(names = structure(c(1L, 3L, 2L), .Label = c("ALBERT | ALBERTIS 2", 
"ALBERTOS", "PIERRE | JEAN | ALBERT"), class = "factor")), class = "data.frame", row.names = c(NA, 
-3L))

data2 <- structure(list(names_search = structure(1:2, .Label = c("ALBERTIS 2", 
"PIERRE"), class = "factor")), class = "data.frame", row.names = c(NA, 
-2L))

Upvotes: 1

Related Questions