Using column names as arguments in existing functions in dplyr mutate()?

Viewed 76

I have a data frame:

df <- data.frame(ID=LETTERS[1:3], Text=c("A/B", "C/D","B/C"))

  ID Text
1  A  A/B
2  B  C/D
3  C  B/C

I want to check, for each row, if the value in ID is present in Text:

# desired output
  ID Text Present
1  A  A/B TRUE
2  B  C/D FALSE
3  C  B/C TRUE

Using the column names in conjunction with mutate() and grepl() does not work (third row is incorrect):

df %>% mutate(Present=grepl(pattern=ID, Text))
  ID Text Present
1  A  A/B  TRUE
2  B  C/D FALSE
3  C  B/C FALSE

Warning message:
Problem with `mutate()` column `Match`.
ℹ `Match = grepl(pattern = ID, Text)`.
ℹ argument 'pattern' has length > 1 and only the first element will be used 

I know dplyr has some requirements with how to specify variables as arguments, but I can only find examples of people running into an issue writing their own functions, whereas I want to use an existing function. I've tried those techniques anyways:

df %>% mutate(Present=grepl(pattern={{ ID }}, Text))
Error in (function (arg)  : object 'ID' not found

df %>% mutate(Present=grepl(pattern=.data$ID, Text))
  ID Text Present
1  A  A/B    TRUE
2  B  C/D   FALSE
3  C  B/C   FALSE
Warning message:
Problem with `mutate()` column `Present`.
ℹ `Present = grepl(pattern = .data$ID, Text)`.
ℹ argument 'pattern' has length > 1 and only the first element will be used 
# same issue as previous code block

df %>% mutate(Present=grepl(pattern=enquo(ID), Text))
  ID Text Present
1  A  A/B   FALSE
2  B  C/D   FALSE
3  C  B/C   FALSE
Warning message:
Problem with `mutate()` column `Present`.
ℹ `Present = grepl(pattern = enquo(ID), Text)`.
ℹ argument 'pattern' has length > 1 and only the first element will be used 

df %>% mutate(Present=grepl(pattern= .data[[ID]], Text))
Error in splice(dot_call(capture_dots, frame_env = frame_env, named = named,  : 
  object 'ID' not found

df %>% mutate(Present=grepl(pattern=!!ID, Text))
Error in splice(dot_call(capture_dots, frame_env = frame_env, named = named,  : 
  object 'ID' not found

df %>% mutate(Present=grepl(pattern=!!enquo(ID), Text))
Error in (function (arg)  : object 'ID' not found

df %>% mutate(Present=grepl(pattern=enquo(!!ID), Text))
Error in splice(dot_call(capture_dots, frame_env = frame_env, named = named,  : 
  object 'ID' not found

I'm at a loss. This feels like it should be a really simple thing to do.

1 Answers

The str_detect solution in the comments is good. You could also use purrr::map2_lgl to make the grepl act across rows.

library(dplyr)
library(purrr)

df %>% 
  mutate(Present = map2_lgl(ID, Text, grepl))

  ID Text Present
1  A  A/B    TRUE
2  B  C/D   FALSE
3  C  B/C    TRUE
Related