Brandon
Brandon

Reputation: 1904

Using `:=` from rlang to assign column names using lapply function inputs

I am trying to loop across a vector of patterns/strings to both match strings within another column and assign the results to a column of the same name as the pattern being searched. A simple example is below.

I am aware that this example is trivial but it captures the minimal case that produces the error that I cannot resolve.

> library(rlang)
> library(stringr)
> library(dplyr)
> set.seed(5)
> df <- data.frame(
+   groupA = sample(x = LETTERS[1:6], size = 20, replace = TRUE),
+   id_col = 1:20
+ )
> 
> mycols <- c('A','C','D')
> 
> dfmatches <- 
+   lapply(mycols, function(icol) {
+   data.frame(!!icol := grepl(pattern = icol, x = df$groupA))
+ }) %>% 
+   cbind.data.frame()

This gives me the error:

 Error: `:=` can only be used within a quasiquoted argument

The desired output would be a data.frame like the below:

> dfmatches
       A     C     D
1  FALSE FALSE FALSE
2  FALSE FALSE FALSE
3  FALSE FALSE FALSE
4  FALSE FALSE FALSE
5   TRUE FALSE FALSE
6  FALSE FALSE FALSE
7  FALSE FALSE  TRUE
8  FALSE FALSE FALSE
9  FALSE FALSE FALSE
10  TRUE FALSE FALSE
11 FALSE FALSE FALSE
12 FALSE  TRUE FALSE
13 FALSE FALSE FALSE
14 FALSE FALSE  TRUE
15 FALSE FALSE FALSE
16 FALSE FALSE FALSE
17 FALSE  TRUE FALSE
18 FALSE FALSE FALSE
19 FALSE FALSE  TRUE
20 FALSE FALSE FALSE

I've tried multiple variations using {{}} or !! rlang::sym() etc but cannot quite figure out the right syntax for this.

Upvotes: 0

Views: 144

Answers (1)

Ronak Shah
Ronak Shah

Reputation: 388972

One option is to use map_dfc from purrr. Also I think you don't need grepl since here we are looking for an exact match and not partial one.

library(dplyr)
library(purrr)

map_dfc(mycols, ~df %>% transmute(!!.x := groupA == .x))

In base R, we can do

setNames(do.call(cbind.data.frame, lapply(mycols, 
                 function(x) df$groupA == x)), mycols)

Upvotes: 2

Related Questions