I saw someone ask a similar question to this but did not have a conclusive answer... I am trying to knit an rmd file to html and am using a function that I wrote in a .R file. I get an error saying the function can not be found etc.
Also just a note that when I run the chunk of code that the function is called for, it works. Just an error when knitting.
This is because you're using the knit button in Rstudio which creates a new session then executes rmarkdown::render, in order to use locally defined function you have to call rmarkdown::render from the console.
Note: that this will block the console until the .Rmd file is rendered.
my.envir <- new.env(parent=baseenv())
local({
f <- function() { ... }
#...
}, my.envir)
# OR source your file directly into my.envir
source("ur.file.R", local = my.envir)
rmarkdown::render(input, # path to the .Rmd file
output_format = "html_document", # output type if not set it'll use the first one found in the yaml header
output_file = NULL, # name of the output file by default it will be the
# name of the .Rmd with the extension changed
clean = TRUE, # set to FALSE if you want to keep intermediary files
envir = my.envir, # this where the magic happens
# if you don't want to modify the global env you can create your own environment and add the function to it
quiet = FALSE # set to TRUE if you want to suppress the output
)
EDIT following #KonardRudolph's comments:
It's better to source your file into the rmd itself, as the main goal of Rmarkdown is reproducible research.
```{r setup, include=FALSE}
.
.
.
source("path/to/file.R")
```
Related
Suppose i have a main R-Markdown file called index.Rmd and another R-Markdown file called child.Rmd. If i want to include the R-Markdown file child.Rmd based on the condition params$value1 > params$value2, i can add the following code to the file index.Rmd
condition <- params$value1 > params$value2
filepathToChild <- "/home/user/child.Rmd"
```{r conditional_print,
child=filepathToChild , eval = condition
}
```
Using bookdown, i can create a file called _bookdown.yml with the following content to include the content of the file child.Rmd after the content of the file index.Rmd:
rmd_files: ["index.Rmd", "child.Rmd"]
How can i include the content of the file child.Rmd in bookdown based on the condition params$value1 > params$value2?
I can't think of a solution to do it in yml, but you could create that yml-file programmatically and combine it with the rendering process.
Just create a simple script to generate the .yml-file and do the rendering:
# compile_my_book.R
# get the parameters
param1 <- commandArgs(trailingOnly = TRUE)[1]
param2 <- commandArgs(trailingOnly = TRUE)[2]
# just some dummy yml from bookdown examples
my_yml <- paste0(
"book_filename: 'my-book.Rmd'
before_chapter_script: ['script1.R', 'script2.R']
output_dir: 'book-output'
clean: ['my-book.bbl', 'R-packages.bib']"
)
# list the files
# (here you could also use list.files to get them automatically, sorting them etc.)
my_files <- c("chapter01.Rmd", "chapter02.Rmd", "References.Rmd")
# add your conditional files
if (param1 > param2) my_files <- c(my_files, "conditional.Rmd")
# create the _bookdown.yml
cat(my_yml,
"\nrmd_files: ['", paste0(my_files, collapse = "', '"), "']",
file = "_bookdown.yml", sep = "")
# render your book with the arguments you want (excluding the values you want to check for)
bookdown::render_book('index.Rmd', 'bookdown::gitbook')
Then you could compile the book from command line:
Rscript compile_my_book.R value1 value2
(or create a makefile or something similar to run multiple things for you)
So running Rscript compile_my_book.R 1 2 does not add the conditional files, but Rscript compile_my_book.R 2 1 does it.
It's a bit hacky, but I'm using similar workflows to create long .xml-config files for some web apps I use, by reading in data from several sources, checking some conditions and creating the config file.
Another way is simply to put all your chapter's code in another Rmd(child2.Rmd), to call it in child.Rmd and to add an eval condition :
```{r, child= 'child.Rmd',eval=params$value1 > params$value2}
```
And you change nothing to your yml.
I teach a lab and I have my students write their answers in .Rmd files. For grading, I download and render them as pdfs in a batch. I use the following script to render everything and save in a file.
library(rmarkdown)
# Handy functions for concatenating strings because I want to do it like a Python
# programmer damnit!
`%s%` <- function(x,y) {paste(x,y)}
`%s0%` <- function(x,y) {paste0(x,y)}
# You should set the working directory to the one where the assignments are
# located. Also, make sure ONLY .rmd files are there; anything else may cause
# a problem.
subs <- list.files(getwd()) # Get list of files in working directory
errorfiles <- c() # A vector for names of files that produced errors
for (f in subs) {
print(f)
tryCatch({
# Try to turn the document into a PDF file and save in a pdfs subdirectory
# (you don't need to make the subdirectory; it will be created automatically
# if it does not exist).
render(f, pdf_document(), output_dir = getwd() %s0% "/pdfs")
},
# If an error happens, complain, then save the name in errorfiles
error = function(c) {
warning("File" %s% "did not render!")
warning(c)
errorfiles <- c(errorfiles, f)
})
}
This last assignment I forgot to set error=TRUE in the chunks, so documents will fail to compile if errors are found and I will have to go hunt those errors down and fix them. I tried to modify this code so that I set the parameter error=TRUE as default outside the document. Unfortunately, I've been working at this for hours and have found no way to do so.
How can I change this code so I can change this parameter outside the documents? (Bear in mind that I don't own the computer so I cannot install anything, but the packages knitr and rmarkdown are installed.)
Is there a way to test-out and peek at the output of a selected portion of markdown in RStudio? It seems you either run R code or have to compile the entire RMD page in order to see the output.
This is a Windows-only solution and it uses the clipboard instead of the current selection:
Define the following function:
preview <- function() {
output <- tempfile(fileext = ".html")
input <- tempfile(fileext = ".Rmd")
writeLines(text = readClipboard(), con = input)
rmarkdown::render(input = input, output_file = output)
rstudioapi::viewer(output)
}
Then, copy the markdown you want to preview and run preview(). Note that the output might be different from the output in the final document because
the code is evaluated in the current environment
only the copied markdown is evaluated, meaning that the snippet has no context whatsoever.
A solution without using the clipboard will most likely employ rstudioapi::getActiveDocumentContext(). It boils down to something along the lines of a modified preview function
preview2 <- function() {
code <- rstudioapi::getActiveDocumentContext()$selection
# drop first line
# compile document (as in preview())
# stop execution (THIS is the problem)
}
which could be used by running preview() followed by the markdown to render:
preview2()
The value of pi is `r pi`.
The problem is, I don't see how the execution could be halted after calling preview2() to prevent R from trying to parse The value of …. See this related discussion.
My render function to create the html file from the rmd file is as follows:
createReports <- reactive({
annual <- (some data...)
.....
rmarkdown::render(
input = RMD_FILE,
output_format = "html_document",
output_dir = "outputTest",
quiet = TRUE
)
However, when I run this line, The Rmd file loads fine but I get this error:
Quitting from lines 15-21 (5_Year_Average_Dividend_Growth_Rate.Rmd)
Error in nrow(annual) : object 'annual' not found
However, as you can see, I have defined the variable annual within the same function as the rmarkdown::render. However, when it goes into the function render, it does not recognize that there is a variable called annual. I debugged it and right before it goes into rmarkdown::render, the annual variable does exist. How can I fix this?
What you need is, in the rmarkdown document code chunk section where the variable annual is used, set the chunk to be
```{r annual}
your_code_that_uses_annual_variable
```
I have a shiny app that allows the user to download an HTML file (knitted from a .Rmd file) that includes the code used to run the analysis based on all the user inputs. I am trying to write the base .Rmd file that gets altered when user inputs vary. I am having trouble including user input variables (e.g. input$button1) into R code chunks. Say the user input for input$button1 = "text1".
```{r}
results <- someFun(input$button1)
```
And I'd like to have it knitted like this:
```{r}
results <- someFun('text1')
```
Every time I download the knitted HTML though, I get input$button1 getting written to file. I would also like to be able to produce an .Rmd file that is formatted with this substitution. It seems like knit_expand() might be the key, but I can't seem to relate available examples to my specific problem. Is the proper way to knit_expand() the whole .Rmd file and specify explicitly all the parameters you want subbed in, or is there a more elegant way within the .Rmd file itself? I would prefer a method similar to this, except that instead of using the asis engine, I could use the r one. Any help would be greatly appreciated. Thanks!
Got it. Solution below. Thanks to Yihui for the guidance. The trick was to knit_expand() the whole .Rmd file, then writeLines() to a new one, then render. With hindsight, the whole process makes sense. With hindsight.
For the example, p1 is a character param 'ice cream' and p2 is an integer param 10. There is a user-defined param in ui.R called input$mdType that is used to decide on the format provided for download.
Rmd file:
Some other text.
```{r}
results <- someFun("{{p1}}", {{p2}})
```
in the downloadHandler() within server.R:
content = function(file) {
src <- normalizePath('userReport.Rmd')
# temporarily switch to the temp dir, in case you do not have write
# permission to the current working directory
owd <- setwd(tempdir())
on.exit(setwd(owd))
file.copy(src, 'userReport.Rmd')
exp <- knit_expand('userReport.Rmd', p1=input$p1, p2=input$p2)
writeLines(exp, 'userReport2.Rmd')
out <- rmarkdown::render('userReport2.Rmd', switch(input$mdType,
PDF = pdf_document(), HTML = html_document(), Word = word_document()))
}
file.rename(out, file)
}
Resulting userReport2.Rmd before rendering:
```{r}
results <- someFun("ice cream", 10)
```