Check if string contains anything other than items in vector [R]

Viewed 692

I have a dataframe containing a column of strings. I want to check whether any of the elements in each string match any of the elements in one or more predefined vectors, and then return a new logical column. This is easily accomplished using grepl().

However (and this is the part I need help with), I also want to check whether the strings contain any elements other than those contained in the keyword vectors.

Example data:

matchvector1 <- c("Apple","Banana","Orange")
matchvector2 <- c("Strawberry","Kiwi","Grapefruit")

id <- c(1,2,3)
string_column <- c(paste0(c("Apple","Banana"),collapse=", "), paste0(c("Strawberry","Kiwi"), collapse = ", "), paste0(c("Apple","Pineapple"), collapse = ", "))
df <- data.frame(id, string_column)
df$string_column <- as.character(df$string_column)

matches_vector1 <- grepl(paste(matchvector1, collapse = "|"), df$string_column)
matches_vector2 <- grepl(paste(matchvector2, collapse = "|"), df$string_column)

The output should look something like:

matches_vector1: TRUE FALSE TRUE
matches_vector2: FALSE TRUE FALSE
unmatched_words: FALSE FALSE TRUE

I'm stuck on this last part. Is there an easy way to match on anything except something in a list of keywords using grepl() (or another function)? I suspect it will involve using negative lookaround somehow but the few existing threads on this didn't seem to answer my question.

1 Answers

One option is to split the 'string_column' with separate_rows, grouped by 'id', check if there are not any elements from 'string_column' %in% the concatenated vectors

library(dplyr)
library(tidyr)
df %>%
   separate_rows(string_column) %>%
   group_by(id) %>% 
   summarise(unmatched = any(!string_column %in% c(matchvector1, matchvector2)) )
# A tibble: 3 x 2
#     id unmatched
#* <dbl> <lgl>    
#1     1 FALSE    
#2     2 FALSE    
#3     3 TRUE     

or in base R

lengths(sapply(strsplit(df$string_column, ",\\s*"), 
      setdiff, c(matchvector1, matchvector2))) > 0
#[1] FALSE FALSE  TRUE
Related