Reputation: 31
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
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