Skip to content

Instantly share code, notes, and snippets.

@moodymudskipper
Last active October 16, 2018 01:48
Show Gist options
  • Save moodymudskipper/ec838d6b87ad823c9089dc1ed9d601a6 to your computer and use it in GitHub Desktop.
Save moodymudskipper/ec838d6b87ad823c9089dc1ed9d601a6 to your computer and use it in GitHub Desktop.
pass parameters and run a rmd report in a "clean environment"
# this function will run a rmd report in a "clean environment", which means it
# ignores what's in the global environment and what packages have been attached.
# It can be fed adhoc parameters however.
#
# "clean environment" is between quotes because loaded namespaces in the
# original environment CAN influence the report, and the rmd rendering CAN alter
# the loaded namespaces.
#
# In practice this should not be an issue in most cases but let it be said that
# the only known way to be sure about the reproduciblity of a report is to knit
# it in a new session.
#
# As a last note, the following overwrites library locally and uses attach
# (2 times!), you've been warned.
#
# Read on below for an example (result : https://jsfiddle.net/cLya01qu/ )
create_report <- function(.rmd, .html, ..., unload = FALSE){
# get loaded packages "package:*" strings
packages <- grep("^package:",search()[1:(match("package:stats",search())-1)],value = TRUE)
# cleanup and save search path
sapply(packages, detach, character.only = TRUE)
search_ <- search()
# set back to normal in the end
on.exit({
# remove whatever was attached during the rendering
sapply(setdiff(search(),search_),detach, character.only = TRUE)
# reattach the original packages
sapply(rev(gsub("^package:","",packages)), library, character.only=TRUE)
})
# define a new library function locally so our rmd attaches packages after
# our attached environment
library2 <- function(...) {
dots <- alist(...)
if("pos" %in% names(dots)) dots$pos <- dots$pos + 1
else dots$pos <- 3
do.call(base::library,dots)
}
attach(list(library = library2),pos = 2,name = "library_env")
attach(list(...), pos = 2,name = "render_env")
rmarkdown::render(.rmd, output_format = "html_document",
output_file = .html,
envir = as.environment("render_env"))
detach("render_env")
detach("library_env")
}
######################################
# EXAMPLE #
######################################
rmd_input <- tempfile(fileext = ".Rmd")
html_output <-tempfile(fileext = ".html")
# create the rmd file
# you must correct the indentation if you copy this in R Studio!
# (Alt + select and suppr is your friend!)
cat(
'---
title: "Parametric report"
output: html_document
---
```{r}
library("data.table")
search() # only data.table, no tidyverse package!
ls() # clean workspace, contains only fed parameters
x <- "don\'t you ignore me!"
for (obj in c("x","y","z","as_tibble","as.data.table")){
if(is.null(get0(obj)))
print(paste(obj,"was NOT found"))
else
print(paste(obj,"was found"))
}
ggplot2::qplot(0,0, geom="text",
label="I can also call use \'fun::pkg\' notation for unattached packages")
```',file = rmd_input)
# if you want to open it:
# file.edit(rmd_input)
# let's populate our search path
library(tidyverse)
library(rlang)
search()
# [1] ".GlobalEnv" "package:rlang" "package:forcats" "package:stringr"
# [5] "package:dplyr" "package:purrr" "package:readr" "package:tidyr"
# [9] "package:tibble" "package:ggplot2" "package:tidyverse" "tools:rstudio"
# [13] "package:stats" "package:graphics" "package:grDevices" "package:utils"
# [17] "package:datasets" "package:methods" "Autoloads" "package:base"
# now let's populate the workspace
y <- "I will be fed to the report"
z <- "I won't"
# and now create a report from `y` only :
create_report(rmd_input, html_output, y = y)
# and open the result : works on windows, not sure on other systems!
shell(html_output)
# we get our clean path back
search()
# cleanup
# file.remove(rmd_input)
# file.remove(html_output)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment