cynkra / dm

Working with relational data models in R
https://dm.cynkra.com
Other
502 stars 49 forks source link

can we use dm_filter with a variable for the table name? #2235

Closed smgogarten closed 1 month ago

smgogarten commented 1 month ago

I'd like to be able to embed dm_filter in a function that filters a table with an arbitrary table name, column and value. Unquoting the column name can be done with !!sym(), but I've tried several ways of unquoting the table name and can't find any that work. Is this possible now, or can it be made possible in the future?

subject <- tibble(
    subject_id = c("subject1", "subject2", "subject3"),
    phenotype = 1:3
)
sample <- tibble(
    sample_id = c("sample1", "sample2", "sample3"),
    subject_id = c("subject1", "subject2", "subject3")
)
my_dm <- dm(subject, sample) %>%
    dm_add_pk(subject, subject_id) %>%
    dm_add_pk(sample, sample_id) %>%
    dm_add_fk(sample, subject_id, subject, subject_id)

dm_filter(my_dm, subject = (subject_id == "subject1")) # OK

# want to embed this in a function
my_table <- "subject"
my_column <- "subject_id"
my_value <- "subject1"
dm_filter(my_dm, subject = (subject_id == my_value)) # OK
dm_filter(my_dm, subject = (!!sym(my_column) == my_value)) # OK
dm_filter(my_dm, !!sym(my_table) = (!!sym(my_column) == my_value)) # error
> Error: unexpected '=' in "dm_filter(my_dm, !!sym(my_table) ="

dm_filter(my_dm, setNames((!!sym(my_column) == my_value), my_table)) # error
> Error in dm_filter_api1(..., call = call, user_env = user_env, target = target,  : 
  quo_is_symbol(table) is not TRUE

dm_filter(my_dm, setNames((!!sym(my_column) == my_value), !!sym(my_table))) # same error
dm_filter(my_dm, setNames((!!sym(my_column) == my_value), !!!my_table)) # same error
moodymudskipper commented 1 month ago

dm_filter(my_dm, !!sym(my_table) = (!!sym(my_column) == my_value)) cannot work because it's not syntactic, no package can make this work, however this will work if you use := instead, this works similarly with tidyverse functions.

dm_filter(my_dm, !!sym(my_table) := (!!sym(my_column) == my_value))

Another solution

dm_filter(my_dm, "{my_table}" := (!!sym(my_column) == my_value)) 
smgogarten commented 1 month ago

That is very helpful, thank you! I didn't know about the := syntax.