Search code examples
rtibbletidyeval

Generate tibbles with different column names with map2()


I have a character vector of names and a list of numeric vectors. I would like to create tibbles with one column each where the column names come from the character vector and the should be populated with the values from the numeric vectors.

Here is a minimal example of what I tried:

names <- c("col1", "col2")

cols <- list(1:10, 11:20)

map2(.x = !!!rlang::syms(names), .y = cols, ~tibble::tibble(.x = .y))

When I run this, I get an invalid argument type error. From what I understand (and what I tried), I cannot simply use names as .x. Then the column names would be .x instead of col1 or col2. By using syms and unquoting the expression I tried to convert the character elements from names into names which I was thinking were needed.

EDIT: Benchmark on suggested solutions:

Both suggested solutions work well and are easy to read. Thus, I conducted a small benchmark to help me choose which solution to accept. The (accepted) solution using !! is faster and a little shorter.

Unit: microseconds
      expr      min        lq      mean    median       uq      max neval
 set_names 1148.635 1163.1985 1210.2218 1168.8840 1201.048 3950.820   100
        !!  701.961  713.5295  729.4239  721.2395  734.779 1102.086   100

Solution

  • map2() is a regular function so does not support !!. Since it is tibble() that does the quoting here, that's where you should unquote:

    map2(names, cols, function(n, x) tibble::tibble(!!n := x))
    

    Note that you don't need sym() to unquote names on the LHS because both symbols and strings are supported (this is standard in R, you can always supply names as strings or symbols, e.g. list("str" = 1, sym = 2)).