How to identify and retrieve multiple patterns from multiple texts?

Viewed 70

I hope this does not get marked as duplicated. I have seen similar stackoverflow posts but I cannot make it work for me.

My goal: 1st: I want to detect in main_df , if the variable 'Code' in auxiliary_df is there. 2nd: After having detected I want to create a column, with the identified codes. For example, for the text 'School Performance, I want to have a line like 'A1, A6, A7'.

main_df <- read.table(header = TRUE, 
                   stringsAsFactors = FALSE, 
                   text="Title Text
'School Performance' 'Students A1, A6 and A7 are great'
'Groceries Performance' 'Students A9, A3 are ok'
'Fruit Performance' 'A5 and A7 will be great fruit pickers'
'Jedi Performance' 'A3, A6, A5 will be great Jedis'
'Sith Performance' 'No one is very good. We should be happy.'")



auxiliary_df <- read.table(header = TRUE, 
                   stringsAsFactors = FALSE, 
                   text="FirstName Code
'Alex' 'A1'
'Figo' 'A6'
'Rui' 'A7'
'Deco' 'A5'
'Cristiano' 'A9'
'Ronaldo' 'A3'")

What I tried:

toMatch <- auxiliary_df$Code

matches <- grep(paste(toMatch, collapse = "|"), 
                main_df$Title, value=TRUE)

matches #returns character(0)

I did not manage to identify any of the codes and move them to the new variable.

The desired output would look like this:

'School Performance' 'Students A1, A6 and A7 are great' 'A1, A6, A7'

Any help is welcome!

2 Answers

You try to match with main_df$Title instead of main_df$Text. You can use gregexpr with regmatches to extract the hits (using mainly your code).

regmatches(main_df$Text, gregexpr(paste(auxiliary_df$Code, collapse = "|"),
 main_df$Text))
#[[1]]
#[1] "A1" "A6" "A7"
#
#[[2]]
#[1] "A9" "A3"
#
#[[3]]
#[1] "A5" "A7"
#
#[[4]]
#[1] "A3" "A6" "A5"
#
#[[5]]
#character(0)
#

We can use collapse all the Code into one pattern and use str_extract_all to extract all the codes that appear in Text and combine them into one comma-separated string.

main_df$extract_string <- sapply(stringr::str_extract_all(main_df$Text, 
             paste0('\\b', auxiliary_df$Code, '\\b', collapse = '|')), toString)
main_df

#                  Title                                     Text extract_string
#1    School Performance         Students A1, A6 and A7 are great     A1, A6, A7
#2 Groceries Performance                   Students A9, A3 are ok         A9, A3
#3     Fruit Performance    A5 and A7 will be great fruit pickers         A5, A7
#4      Jedi Performance           A3, A6, A5 will be great Jedis     A3, A6, A5
#5      Sith Performance No one is very good. We should be happy.               

Added word boundaries (\\b) in the pattern so that A1 do not get matched with A11 or A110 if it is not present in the Text.

Related