Reputation: 993
On Windows 7 64 bits, I have recently updated to RStudio 1.1.383 and rmarkdown 1.7. As I am using render
to produce a pdf from an Rmd file I have noticed a new behavior.
x = 12
in the .Rmd file, I find x
in the Global environment after the render is complete. y
in the .Rmd and I set y=1000
in the global environment before using render
then y
is used in the knitting of the .Rmd y
is defined in the global environment, knitting the .Rmd will give an error (y not found).Does anyone know why is that? I believe separating the environment is very important to ensure reproducibility even though it is sometimes painful to get right.
Here is my sessionInfo()
:
> sessionInfo()
R version 3.4.2 (2017-09-28)
Platform: x86_64-w64-mingw32/x64 (64-bit)
Running under: Windows 7 x64 (build 7601) Service Pack 1
Matrix products: default
locale:
[1] LC_COLLATE=English_United States.1252 LC_CTYPE=English_United States.1252 LC_MONETARY=English_United States.1252
[4] LC_NUMERIC=C LC_TIME=English_United States.1252
attached base packages:
[1] stats graphics grDevices utils datasets methods base
other attached packages:
[1] rmarkdown_1.7
loaded via a namespace (and not attached):
[1] compiler_3.4.2 backports_1.1.1 magrittr_1.5 rprojroot_1.2 htmltools_0.3.6 tools_3.4.2 yaml_2.1.14 Rcpp_0.12.13
[9] stringi_1.1.5 knitr_1.17 stringr_1.2.0 digest_0.6.12 evaluate_0.10.1
Here is the minimal "test render.R" file:
library(rmarkdown)
y=1000
render(input = "test render.Rmd")
and Here is the minimal "test render.Rmd" file:
---
title: "test render"
author: "Courvoisier"
output: pdf_document
---
## R Markdown
```{r cars}
x = 12
print(y)
```
and here is the pdf result:
Upvotes: 1
Views: 283
Reputation: 30174
As far as I can tell, this behavior has been there since Day 1. Here is how to prove it. First install the very first version (0.3.3) of rmarkdown from the CRAN archive:
devtools::install_version('rmarkdown', '0.3.3')
And run your example:
library(rmarkdown)
y = 1000
render(input = "test render.Rmd")
You see y
is printed (as I'd expect):
This behavior is by design and I don't know why it is surprising to you. In R, global variables are accessible from anywhere (by definition). You defined y
in the global environment, and you should expect it to be accessible in the R Markdown document, too.
The R Markdown document is compiled in the environment parent.frame()
of render()
, and all variables will be created in this environment. In your case, parent.frame()
is the global environment (i.e. globalenv()
), and that explains why x
was created in the global environment.
When you click the Knit button in RStudio, it is different because the document is compiled in a separate new (clean) R session. The variable y
you defined in the current R session will not be available to the new R session. Similarly, x
will be created in the new session and not in your current R session. Reproducibility is exactly why we chose to compile R Markdown documents in new R sessions instead of the current R session. If a document works in a new R session, it is more likely to be reproducible. If it works in your current R session (via rmarkdown::render()
), it might just work by chance.
If you have to evaluate code chunks in a separate environment, you need to use the argument envir
explicitly, e.g.
render(input = "test.Rmd", envir = new.env())
This way, x
will not be created in your global environment, but y
will be available to the code chunk (again, by definition of global variables).
In all, if you really care about reproducibility (like we do), there is an easy way and a slightly harder way. The easy way is to click the Knit button in RStudio, and the harder way is to render the document in a separate R session by yourself, e.g., via the command line
Rscript -e "rmarkdown::render('test.Rmd')"
Upvotes: 2