0

I got difference in output using "Knit to HTML" button and rmarkdown::render() which I figured out was related to environment. I'd like to know what exactly is the difference in environment so that I can fully understand what has happened. Here was my observation:

var1 <- "" 
var1 <<- some code that creates a new value

With the above setting, the resulting observations are listed below. (The var needs to be pushed to global for a subsequent function to work. I know it's not a good practice, but a much quicker workaround than to figure out how to improve the function which has multiple nested functions.):

  • run the chunks in Rstudio: the subsequent function gets the new var value and works
  • "Knit to HTML" button: the subsequent function gets the new var value and works
  • rmarkdown::render (in another file that calls the main code file): gets var="" and fails with this error message: Error in approx(sp$y, sp$x, xout = cutoff) : need at least two non-NA values to interpolate
# then adding the additional line here made it work in rmarkdown::render()
var1 <- "" 
var1 <<- some code that creates a new value
var1 <- same code to create the new value as above
  • the subsequent function in all cases gets the new var value and work

Note that a previous chunk that uses the first setting (only save to global) did not get error in rmarkdown::render(). So what's the difference in the three ways of running the code in terms of environment?

ADDED later: I later found out that putting the arguments for the nested function in a list and call the function using do.call works in the rmarkdown::render() without using global variables. I give a simple example below. Why do.call makes a difference in the render call?

os1 <- function(OSdf, strata_name) {
  form <- as.formula(paste("Surv(tte, status) ~", strata_name))
  KMfit <- do.call(survfit, args = list(formula = form, data = OSdf, conf.type = "log-log"))
}
Pumbaa
  • 70
  • 7
  • Pumbaa, I know this is an old (and unanswered) question, but my thoughts. My opinion, but never ever ever have an rmarkdown document rely on variables in the global environment. Treat the document like a `function`, where the functions arguments are given to the document as [rmarkdown parameters](https://rmarkdown.rstudio.com/developer_parameterized_reports.html%23parameter_types%2F). And like a good no-side-effect `function`, within the Rmd, you either get data from `params$` or you create a variable, anything else is a mistake. (This includes `library(...)`, as necessary.) – r2evans May 20 '20 at 15:31
  • BTW: I think naming a variable `var` is a bad idea because it is the same name as a function in `stats`. While R normally gets it right (and references `stats::var` when you try `var(1:3)`), it does not always get it right. Try `var <- "A"; sapply(list(1:3, 2:4), var); sapply(list(1:3, 2:4), stats::var)`. Also, if you forget to assign `var <- list(a=1,b=2)` and then do `var$a`, you'll get an evasive error: `object of type 'closure' is not subsettable`. If you know that a "closure" is just a function with an enclosing environment, it *might* make sense, but the error is otherwise perplexing. – r2evans May 20 '20 at 15:36
  • Thanks @r2evans for the response. I know that using global variables in this situation is not good. That's why I'd like to understand the underlying reason. I did find out that using do.call and put the arguments for the nested functions into lists gets around the problem without using global variables. I posted above and hope that someone can shed some light on why it makes a difference. And yes, the "var" is just a dummy example. I updated it now. Thanks again. – Pumbaa May 24 '20 at 01:24

0 Answers0