#' Set function parameters to an environment.
#'
#' This function is designed to help debug functions. It will attempt to set all
#' the default parameter values to the specified environment (global environment
#' by default). This is useful for when you want to execute code within the
#' function definition interactively but need the parameters set in the current
#' environment.
#'
#' **Warning:** This function will modify the global environment and therefore
#' violates CRAN policy
#' ["Packages should not modify the global environment (user’s workspace)"]
#' (https://cran.r-project.org/web/packages/policies.html#Source-packages).
#'
#' @param FUN the function to assign parameters to an environment.
#' @param envir the environment to assign the variables to. Defaults to the
#' global environment.
#' @param verbose whether to return the data frame invisibly or to print the results.
#' @return a data frame where row names correspond to the parameter name with
#' two columns: `set` which is logical indicating if the variable was set
#' and `value` with a character representation of the variable value.
set_function_params <- function(FUN, envir = globalenv(), verbose = interactive()) {
params <- formals(FUN)
params_set <- data.frame(row.names = names(params),
set = rep(FALSE, length(params)),
value = rep(NA_character_, length(params)))
for(param in names(params)) {
value <- params[[param]]
if(!missing(value)) {
if(is.character(value)) {
assign(param, value, envir = envir)
params_set[param,]$value <- value
} else {
assign(param, eval(value), envir = envir)
params_set[param,]$value <- eval(value)
}
params_set[param,]$set <- TRUE
}
}
if(verbose) {
return(params_set)
} else {
invisible(params_set)
}
}Setting function parameters for debugging
I tend to write a lot of functions that create specific graphics implemented with ggplot2. Although I try to pick graphic parameters (e.g. colors, text size, etc.) that are reasonable, I will typically define all relevant aesthetics as parameters to my function. As a result, my functions tend to have a lot of parameters. When I need to debug the function I need to have all those parameters set in the global environment which usually requires me highlighting each assignment and running it. This function automates this process. You can pass any function and it will attempt to set parameters to the given environment (the global environment by default). It will return a data frame with a column indicating if the variable was set and the value. This is useful to know what parameters don’t have a default value that need to be set yourself.
Very recently I was trying to debug a function that creates profile plots for cluster analysis (clav::profile_plot(), documentation). This function has 23 parameters! Setting these all manually is pretty tedious.
# List objects in the current environment
ls()[1] "set_function_params"
# Call the function
param_set_result <- set_function_params(clav::profile_plot)
# Check to see if the parameters are actually set
ls() [1] "bonferroni" "center_alpha" "center_band"
[4] "center_fill" "cluster_label_hjust" "color_palette"
[7] "hjust" "label_clusters" "label_means"
[10] "label_outcome_means" "label_profile_means" "param_set_result"
[13] "point_size" "se_factor" "set_function_params"
[16] "standardize" "text_size" "title"
[19] "ylab"
We can examine the data frame which gives a summary of the parameters set (or not).
param_set_result set value
df FALSE <NA>
clusters FALSE <NA>
df_dep FALSE <NA>
standardize TRUE TRUE
bonferroni TRUE TRUE
label_means TRUE TRUE
label_profile_means TRUE TRUE
label_outcome_means TRUE TRUE
center_band TRUE 0.25
center_fill TRUE #f0f9e8
center_alpha TRUE 0.1
text_size TRUE 4
hjust TRUE 0.5
point_size TRUE 2
se_factor TRUE 1.96
color_palette TRUE 2
cluster_labels FALSE <NA>
cluster_order FALSE <NA>
label_clusters TRUE TRUE
cluster_label_x FALSE <NA>
cluster_label_hjust TRUE 5
ylab TRUE Mean Standard Score
title TRUE Cluster Profiles