How do I determine how many elements in a vector contain a pattern from a second vector?

Viewed 61

I am trying to determine whether a vector contains multiple patterns. I have vectors names and patterns.

For a simple example I have:

names <- c("john_burgess", "pablo_gorges", "pear_trapper", "john_vaccant")

I would like to know which of the elements in names contains one of the following patterns:

patterns<- c("john", "gorge")

My actual data comprises a names vector of [1:1126] and a patterns vector of [1:1163]. I have been able to work with only one pattern at a time, e.g. "john", but I would like to use all the patterns at once. My desired output would look something like this (so that I could then move on and do further analyses):

names         patterns
john_burgess  john
john_vaccant  john
pablo_gorges  gorge

I have gotten so lost looking through grep, stringr::str_extract, and dplyr::filter help files and only get errors as soon as I try use more than one pattern. I have removed _ in names and it made no difference. I know this must be possible and that it's probably a simple bit of coding but I just can't get it to work. Sorry if this question has already been asked and answered (if so, please point me to it)! I would just really appreciate a nudge in the right direction. Thanks in advance!

3 Answers

Here is an option with tidyverse

library(purrr)
library(tibble)
library(stringr)
map(set_names(patterns, patterns), ~ 
      names[str_detect(names, .x)], .id = 'patterns') %>%
   enframe(name = "patterns", value = "names") %>% 
   unnest(c(names))
# A tibble: 3 x 2
#  patterns names       
#  <chr>    <chr>       
#1 john     john_burgess
#2 john     john_vaccant
#3 gorge    pablo_gorges

Or using base R

stack(lapply(setNames(patterns, patterns), grep, x = names, value = TRUE))

Here is a base R solution using regmatches

df <- data.frame(cbind(names,
                 patterns = regmatches(names,gregexpr(paste0(patterns,collapse = "|"),names))))

such that

> df
         names patterns
1 john_burgess     john
2 pablo_gorges    gorge
3 pear_trapper         
4 john_vaccant     john

DATA

names <- c("john_burgess", "pablo_gorges", "pear_trapper", "john_vaccant")
patterns<- c("john", "gorge")

One way with stringr could be to paste the patterns and extract them using str_extract.

library(stringr)

data.frame(names, patterns = str_extract(names, str_c(patterns, collapse = "|")))

#         names patterns
#1 john_burgess     john
#2 pablo_gorges    gorge
#3 pear_trapper     <NA>
#4 john_vaccant     john
Related