Keep rows which have two string in the same row

Viewed 102

In a dataframe like this:

df <- data.frame(id = c(1,2,3), text = c("hi my name is E","hi what's your name","name here"))

I would like to keep row which contain both hi and name words in a row. Example of expended output:

df <- data.frame(id = c(1,2,3), text = c("hi my name is E","hi what's your name"))

I try this but it doesn't work properly:

library(tidyverse)
df %>%
    filter(str_detect(text, 'name&hi'))
4 Answers

One simple answer and two more complex answers you should really only need if you have more than 2 words to check

library(tidyverse)

df %>% 
  filter(str_detect(text, 'hi') & str_detect(text, 'name'))

df %>% 
  filter(rowSums(outer(text, c('hi', 'name'), str_detect)) == 2)

df %>% 
  filter(reduce(c('hi', 'name'), ~ .x & str_detect(text, .y), .init = TRUE))

We can also use regex to specify whether 'hi' follows 'name' or (|) 'name' follows 'hi

library(dplyr)
library(stringr)
df %>% 
     filter(str_detect(text, 'hi\\b.*\\bname|name\\b.*\\bhi'))

in Base-R

f[grep(".*hi.*name.*",f$text),]

output

  id                text
1  1     hi my name is E
2  2 hi what's your name

Yet another dplyr and stringr option could be:

df %>%
 filter(lengths(str_match_all(text, "name|hi")) == 2)

  id                text
1  1     hi my name is E
2  2 hi what's your name

Or:

df %>%
 rowwise() %>%
 filter(all(c("name", "hi") %in% unlist(str_extract_all(text, "name|hi"))))

Or:

df %>%
 filter(str_count(text, "name|hi") == 2)
Related