tsv
tsv

Reputation: 31

How can I pass column names to tidyr::complete

How do I use tidyr::complete to add additional rows to a data frame, specifying the column names wanted as an input, rather than having to hard code them?

df <- data.frame(
 group = c(1:2, 1),
 item_id = c(1:2, 2),
 item_name = c("a", "b", "b"),
 value1 = 1:3,
 value2 = 4:6
)

This works:

df %>% tidyr::complete(group, item_id, item_name)

but to avoid hardcoding I ideally want this to work:

cols_wanted <- c("group", "item_id", "item_name")
df %>% tidyr::complete(cols_wanted)

But it returns the following error:

Error in `dplyr::full_join()`:
! Join columns must be present in data.
✖ Problem with `cols_wanted`.
Traceback:

1. df %>% tidyr::complete(cols_wanted)
2. tidyr::complete(., cols_wanted)
3. complete.data.frame(., cols_wanted)
4. dplyr::full_join(out, data, by = names)
5. full_join.data.frame(out, data, by = names)
6. join_mutate(x, y, by = by, type = "full", suffix = suffix, na_matches = na_matches, 
 .     keep = keep)
7. join_cols(tbl_vars(x), tbl_vars(y), by = by, suffix = suffix, 
 .     keep = keep, error_call = error_call)
8. standardise_join_by(by, x_names = x_names, y_names = y_names, 
 .     error_call = error_call)
9. check_join_vars(by$y, y_names, error_call = error_call)
10. abort(bullets, call = error_call)
11. signal_abort(cnd, .file)

My current solution is:

eval(parse(text = paste("df %>% tidyr::complete(",
                   paste(noquote(cols_wanted), collapse = ", "),
                   ")")))

But I would like a solution that doesn't use eval or parse

Upvotes: 2

Views: 111

Answers (1)

AndrewGB
AndrewGB

Reputation: 16856

You can use !!!syms with the vector of column names, where syms turns the strings into a list of symbols, then we use the unquote-splice operator, !!!, which passes the list of arguments to complete.

library(tidyverse)

df %>% 
   complete(!!!syms(cols_wanted))

Output

  group item_id item_name value1 value2
  <dbl>   <dbl> <chr>      <int>  <int>
1     1       1 a              1      4
2     1       1 b             NA     NA
3     1       2 a             NA     NA
4     1       2 b              3      6
5     2       1 a             NA     NA
6     2       1 b             NA     NA
7     2       2 a             NA     NA
8     2       2 b              2      5

Upvotes: 3

Related Questions