What is wrong with this tidy eval function?

I am trying to write a function using tidy eval approach. The code works without using the function but I get error with the function. You can see the code with and without the function.

Without a function:

ff <- ds %>% 
  filter(file.ID=="Cars_20160601_01.hdf5") %>% 
  pull(frames) %>% 
  head(.,1)

ado %>% 
  filter(file.ID=="Cars_20160601_01.hdf5") %>% 
  select(ADO_name, frames, pos.2.m, pos.1.m, lane) %>% 
  group_by(ADO_name) %>% 
  do(data.frame(head(., 1))) %>% 
  ungroup() %>% 
  mutate(x.m = pos.2.m + 9857.24,
         y.m = pos.1.m - 84.73 + 456.59) %>% 
  select(-c(pos.2.m, pos.1.m)) %>% 
  mutate(frames2 = frames - ff,
         Time_sec = round((frames2/60),0)) %>% 
  select(-c(frames2, frames)) 
# A tibble: 13 x 5
   ADO_name     lane    x.m   y.m Time_sec
   <chr>        <chr> <dbl> <dbl>    <dbl>
 1 BMWC10       left   5694   458    248  
 2 ditiExpeon6  right  1735   455     12.0
 3 F150C12      right  5856   247    248  
 4 Ford1        left   1477   458     12.0
 5 llacCadi3    right  1193   455     12.0

Function

find_starting_xy <- function(ds, ado, scn){
  
  require(tidyverse)
  require(rlang)
  
  scn <- enquo(scn)
  
  # What is the ID of the 1st frame of External Driver in the scenario?
  first_frame <- ds %>% 
    filter(file.ID== !! scn) %>% 
    pull(frames) %>% 
    head(.,1)
  
  # Starting xy locations of ados in this scenario:
  ado %>% 
    filter(file.ID== !! scn) %>% 
    select(ADO_name, frames, pos.2.m, pos.1.m, lane) %>% 
    group_by(ADO_name) %>% 
    do(data.frame(head(., 1))) %>% 
    ungroup() %>% 
    mutate(x.m = pos.2.m + 9857.24,
           y.m = pos.1.m - 84.73 + 456.59) %>% 
    select(-c(pos.2.m, pos.1.m)) %>% 
    mutate(frames2 = frames - first_frame,
           Time_sec = round((frames2/60),0)) %>% 
    select(-c(frames2, frames)) 
  
}
> find_starting_xy(ds, ado, Cars_20160601_01.hdf5)
 Show Traceback
 
 Rerun with Debug
 Error in filter_impl(.data, quo) : 
  Evaluation error: object 'Cars_20160601_01.hdf5' not found.

Please guide me what I'm doing wrong here?

What this is saying here is that you don't have Cars... (the object above) in your environment. You haven't defined that as an object anywhere yet.

Thanks @mara.

I noticed that if I put quotation marks (see below), it works.

find_starting_xy(ds, ado, "Cars_20160601_01.hdf5")

So, my question is why do I have to put quotation marks even though I have used enquo() and !! with the variable?

Can you please turn this into a reprex (short for minimal reproducible example)? It's much easier to discuss code with code, and the same contents, etc.

(Essentially, it's impossible for me to say without knowing what your data data look like.)

Right now the best way to install reprex is:

# install.packages("devtools")
devtools::install_github("tidyverse/reprex")

If you've never heard of a reprex before, you might want to start by reading the tidyverse.org help page.

For pointers specific to the community site, check out the reprex FAQ, linked to below.

1 Like

As @mara said reprex would be useful, but in the meantime I'm not sure why you need tidy eval in this case.

From your second example the only time you use scn variable is in filter, correct? Then why do you want to pass it as a bare variable? In other words, what exact problem would you have if you pass scn as a string?

If you do pass it as a string, then you don't need to use enquo and !! at all, just write filter(file.ID == scn) and that's it. This way you can change where your data is coming from quite easily.

2 Likes

agreed... the !! is not needed. I can't tell without a reprex, but it seems like a quo(scn) is needed if you are passing the hd5 name unquoted.

1 Like