Search code examples
rr-packagetargets-r-package

Issue with Evaluating Arguments in `tar_script()` for Custom Workflow Function in R Package


I’m developing a function within an R package that is designed to run a targets workflow. The package is currently hosted on GitHub. Here’s a simplified version of the _targets.R script that works when written manually:

#remotes::install_github("derek-corcoran-barrios/SpeciesPoolR")
# If you want to use the package

# _targets.R file
library(targets)
library(crew)

f <- system.file("ex/Species_List.csv", package="SpeciesPoolR")

tar_option_set(packages = c("SpeciesPoolR"),
               controller = crew_controller_local(workers = 4),
               error = "null")  # Skip non-debugging outdated targets

list(
  tar_target(file, command = f, format = "file"),
  tar_target(data, get_data(file,
                            filter = quote(
                              Kingdom == "Plantae" &
                              Class == "Liliopsida"
                            ))),
  tar_target(Clean, SpeciesPoolR::Clean_Taxa(data$Species)),
  tar_target(Count_Presences,
             SpeciesPoolR::count_presences(Clean, country = "DK"),
             pattern = map(Clean))
)

I’m attempting to encapsulate this script into a function within my package, allowing users to customize parameters like the number of workers or the file path. Here's the function I’ve written:

run_workflow <- function(workers = 2,
                         error = "null",
                         file_path) {

  data <- Clean <- clean_species <- NULL

  controller <- substitute(crew::crew_controller_local(workers = workers))
  error_val <- substitute(error)
  file_path_val <- substitute(file_path)

  # Set tar_option_set for the workflow
  targets::tar_script({
    targets::tar_option_set(
      packages = c("SpeciesPoolR"),
      controller = eval(controller),
      error = eval(error_val)
    )

    # Define the targets pipeline
    targets <- list(
      targets::tar_target(file, command = eval(file_path_val), format = "file"),
      targets::tar_target(data, get_data(file)),
      targets::tar_target(Clean, clean_species(data))
    )
  }, ask = FALSE)

  # Run the workflow
  targets::tar_make(targets)
}

However, when I try to run this function:

library(SpeciesPoolR)

f <- system.file("ex/Species_List.csv", package="SpeciesPoolR")

run_workflow(workers = 4,
             error = "null",
             file_path = f)

I encounter an error because the arguments are not being correctly evaluated within the tar_script() call. The generated _targets.R file looks like this:

library(targets)
targets::tar_option_set(packages = c("SpeciesPoolR"), controller = eval(controller), 
    error = eval(error_val))
targets <- list(targets::tar_target(file, command = eval(file_path_val), 
    format = "file"), targets::tar_target(data, get_data(file)), 
    targets::tar_target(Clean, clean_species(data)))

As you can see, controller should be evaluated as crew_controller_local(workers = 4), but instead, it’s just eval(controller). The same issue occurs with file_path.

Question: How can I ensure that the arguments within tar_script() are properly evaluated, so that the correct values are passed to the targets workflow?

Any advice or suggestions on how to resolve this would be greatly appreciated!


Solution

  • Solved it, I mostly changed the function from tar_script to tar_helper

    run_workflow <- function(workers = 2,
                             error = "null",
                             file_path,
                             filter = NULL
                             ) {
    
      data <- Clean <- NULL
    
      # Write the script using tar_helper()
      targets::tar_helper(
        path = "_targets.R",
        code = {
    
          targets::tar_option_set(
            packages = c("SpeciesPoolR"),
            controller =  crew::crew_controller_local(workers = !!workers),
            error = !!error
          )
    
          list(
            targets::tar_target(file, command = !!file_path, format = "file"),
            targets::tar_target(data, get_data(file, filter = !!rlang::enquo(filter))),
            targets::tar_target(Clean, SpeciesPoolR::Clean_Taxa(data$Species))
          )
        },
        tidy_eval = TRUE  # This ensures the !! operators work as expected
      )
    
      # Run the workflow
      targets::tar_make()
    }