Compile a collection of R scripts to HTML with knitr/rmarkdown - r

I have a collection of R scripts in a directory and want to compile them all
to HTML, as I might do using R Studio Compile Notebook manually, but with some control over the CSS styling.
Each file has a minimal YAML header and a bit of markup, as shown below, and I don't want to introduce additional complexity in the scripts with chunk options except where absolutely necessary.
#' ---
#' title: "Tests for association in two-way tables"
#' author: "Michael Friendly"
#' ---
#' ## Load and examine data
library(vcdExtra)
data(SexualFun)
SexualFun # show the table
...
I'm confused about which tools to use to compile a single file in this way--- spin|knit2html, markdownToHTML, etc. Once I get this right, I can use something like apply() to do it for my list of files, files <- list.files(pattern="*.R$").
Here's what I've tried to compile one file, with some additional control:
library(knitr)
options(markdown.HTML.options = markdownHTMLOptions(stylesheet = "markdown.css"))
knit_theme$set("seashell")
opts_chunk$set(fig.align="center")
spinone <- function(file, outdir="output/") {
fn <- knitr:::sans_ext(file)
#+ suppressmessages, include=FALSE
knitr::opts_chunk$set(warning = FALSE, message = FALSE)
spin(file)
Rmd <- knitr:::sub_ext(file, "Rmd")
out <- paste0(outdir, knitr:::sub_ext(file, "html"))
knit2html(Rmd, output=out)
}
But it doesn't work correctly. I get:
> spinone("sexfun-chisq.R")
processing file: sexfun-chisq.Rmd
...
|.................................................................| 100%
ordinary text without R code
output file: sexfun-chisq.md
Error in readLines(if (is.character(input2)) { :
cannot open the connection
In addition: Warning message:
In readLines(if (is.character(input2)) { :
cannot open file 'sexfun-chisq.Rmd': No such file or directory
Actually, sexfun-chisq.html is produced, but it doesn't have the YAML header and doesn't use my style options.

Use spin(file, knit = FALSE) so that the Rmd file will not be deleted (see the precious argument in ?spin).

Related

R markdown / knitr: customize output directory

I am new to Stackoverflow - so please excuse any possible strangeness in my post.
I have a simmilar question as Tom, posted here.
I want to save a pdf created by markdown in a specific directory. After several unsuccessful attempts (including a frustrating chat with GPT), I followed starjas instructions in the post mentioned, yet unsuccessfully.
Here's my YAML header:
---
title: 'MyTitle'
subtitle: 'Analysis XYZ'
author: "Boris et al."
date: "2023-01-22"
knit: (function(input, encoding) {
rmarkdown::render(input,
encoding = "UTF-8",
output_dir = "05-Reports")})
output: pdf_document
---
… and here some code snippets from the scripts main body:
knitr::opts_chunk$set(echo = FALSE, message = TRUE)
source("02-Scripts/03-LogMod-6-plot.R", local = knitr::knit_global())
{r model results} model6.res.table <- simple_kable <- knitr::kable(model6.res, format = "pipe") model6.res.table
Here's the error message I get:
Error in file(filename, "r", encoding = encoding) :
cannot open the connection
Calls: <Anonymous> ... eval_with_user_handlers -> eval -> eval -> source -> file
Execution halted
I believe that the problem has to do something with R not being able to find the output-directory specified (05-Reports). But I have no clue why, as this output-directory is within the working directory:
getwd()
[1] "/Users/my-User/Documents/studyXYZ/1-XYZdata/6-R/studyXYZ-R-Project"
list.files()
[1] "01-Data"               "02-Scripts"            "03-Outputs"          
[4] "04-Plots"              "05-Reports"            "studyXYZ-R-Project.Rproj"
Maybe important to know: I am working with a R-project. Furthermore, in the Global Options under R Markdown, I set "Evaluate chunks in directory:" "Project", as Julius Diel mentioned in a thread regarding a similar topic:
"Error "cannot open the connection" in executing "knit HTML" in RStudio"
 
Before setting R's Global Options like this, I had other issues regarding the scource()-command from my markdown-script adressing the R-scripts containing the analysis-commands. Now the scourcing works fine and I get the results as expected when conducting the markdown script without specifying the output directory (in html and pdf). It's just that the pdf won't be saved where I want it.
 
Does anyone have a clue what causes this problem?
I didn't know about the option Evaluate chunks in directory: "Project". Previously, I used the following in the setup chunk:
knitr::opts_knit$set(root.dir = rprojroot::find_rstudio_root_file())
However, this option is ignored (as well as the option set in RStudio) when using rmarkdown::render in the header of the document. You need to set knit_root_dir to define the root directory from which you the can specify relative paths in source used in your rmarkdown document:
knit: (function(input, encoding) {
rmarkdown::render(input,
output_dir = "05-Reports",
knit_root_dir = rprojroot::find_rstudio_root_file())})

issues knitting R markdown to pdf with psych package

The issue I'm having is after I knit my R-Markdown file to a pdf (or word) document, I get the following error:
However, I have made sure the I have my library(psych) call in my r in which the code chunks are being called from. The describe() call works just fine when I call it in my .r file in r studio, and when I call it inline in the markdown file, but I still get the error when I knit to pdf.
Knitr code referenced in .r file.
## #knitr code_2.2
library(psych)
describe(women_DF)
code chunk in r markdown:
## 2.2 Summarize using describe()
* The `summary` function in base R does not show the number of observations and standard deviation of each variable
+ A convenient alternative to `summary` that includes these statistics is `describe` in the `psych` package
* If you have not already done so, install the `psych` package
+ Console: install.packages("psych") or from Packages → Install dialog
* Recall that you must also call `library(psych)` to load the package into memory
* Now use `describe()` to summarize `women_DF`:
```{r code_2.2}
Setup of r markdown file:
---
title: "Module 1 Workshop"
author: "MSBX-5310 (Customer Analyitcs)"
date: "1/14/2021"
output:
pdf_document: default
word_document: default
---
```{r, include=FALSE}
knitr::opts_chunk$set(
echo = TRUE,
fig.height = 3,
fig.width = 4,
message = FALSE,
comment = NA, error = TRUE)
#uncomment the line below if using an external R script for R chunks
knitr::read_chunk("Workshop1.R")
knitr runs code in its own R session when you click the knit button. This means that anything you have in your environment is not available to that separate session building your document.
In particular, although you did not post your entire Rmarkdown file, it seems the problem is that you didn't load the psych package anywhere in your .Rmd file. You shoould load it somewhere in the Rmarkdown file, either in a separate chunk (if you don't want it to show just before your function call) or in the same chunk where you call one of its functions (in this case, describe()).
```{r code_2.2}
library(psych)
describe(women_DF)

R Markdown - variable output name

With one R markdown file, I would like to create different possible output pdf documents, where the output file name should be defined within the document. Is there any way to convince markdown to manipulate the output filename in such a way? Ideally I would like to pass the filename by an r chunk.
You can keep the simplicity of using the RStudio Knit button and reproducibility of a YAML header by using the undocumented knit hook to redefine what the button does (default function called is rmarkdown::render). The output_file parameter of the render function specifies the file name, so by setting it you override the standard behaviour of using the same prefix as the input filename.
e.g. to always output a file called myfile.pdf
knit: (function(inputFile, encoding) { rmarkdown::render(inputFile, encoding = encoding, output_file = file.path(dirname(inputFile), 'myfile.pdf')) })
The function can be an anonymous one-liner as well as imported from a package, as seen here with slidify.
You can set your own YAML headers (I don't know if this is generally advised anyway), accessible under rmarkdown::metadata$newheader but they don't seem available from within this sort of function as far as I can see.
As for passing file name in from an R chunk... if you're referring to code chunks below the YAML header, from my experience I don't think that's possible(?). Headers can contain inline R commands (single backtick-enclosed, starting with r), but seemingly not for this hook function.
Related:
Rmarkdown GitHub repo issue — output format-specific output_file
Blog post I wrote following this question [invalid link, domain for sale as of 20210216] / corresponding GitHub wiki notes
This is pretty much what I do:
rmarkdown::render('my_markdown_report.Rmd',
output_file = paste('report.', Sys.Date(),
'.pdf', sep=''))
I have three scripts - one pulls the data and process it, second created charts & tables for report. Third one creates report based on markdown file. Code you see above is the part of the third script
I played around with the Knitr-hook without fully understanding how it works and ran into an ugly workaround. The below coding seems to do the trick.
Would be nice if somebody can either explain why it works and/or if it can written less ugly.
For now I lost the shiny input screen but believe this can even be added later. The good thing is that the R-Studio Knit button can still be used.
Please note that the subtitle and the file name are both: This Works! even with space and exclamation mark. The file is saved as This Works!.pdf
The filename and subtitle are set by assigning the text to the object pSubTitle.
Note that the params are still in the YAML but are not resulting in a shiny popup screen as they are assigned in the Knitr-hook
---
params:
sub_title:
input: text
label: Sub Title
value: 'my_Sub_Title_and_File_Name'
title : "Parameterized_Title_and_output_file"
subtitle : "`r params$sub_title`"
output:
pdf_document:
keep_tex: false
knit: (
function(inputFile, encoding) {
pSubTitle <- 'This Works!'
rmarkdown::render(
input = inputFile,
encoding = encoding,
params = list(sub_title = pSubTitle),
output_file = pSubTitle) })
---
```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = TRUE)
```
## R Markdown
This is an R Markdown document. ....
My current solution for this and similar questions is through 2 scripts:
Script1: "xxx.md" file with flexible yaml header, similar to Floris Padt's. This header allows you to generate flexible pdf files with specified title, dates, and other features if you change the params. However, it could not specify flexible pdf names when you render it.
---
params:
feature_input: "XXXA"
date: "08/18/2022"
title: "`Test For `r params$feature_input``"
author: "You Name"
date: "`r params$date`"
output:
pdf_document:
---
```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = TRUE)
```
## R Markdown and data process
```
#Get parameter from yaml head
input_para <- params$feature_input
input_para
```
Script2: "YYY.R", which specify params in xxx.md file, and specify pdf file names by output_file when rendering.
featureNames <- c("aaa", "bbb", "ccc")
setwd("path to xxx.md")
for (currentFeature in featureNames) {
rmarkdown::render("xxx.Rmd",
params = list(feature_input = currentFeature,
date = Sys.Date()),
output_file=paste0("output/",currentFeature))
}
You could update featureNames in yyy.R file, and run yyy.R to get the most flexible use of your xxx.md file.
This solution allows you to:
update yaml header parameters,
apply updated yaml parameters in your .md code chunk,
and save your pdf with specific and flexible names.

Is there a R markdown analog of \SweaveInput{} for modular report generation?

One of the features I like very much in Sweave is the option to have \SweaveInput{} of separate Sweave files to have a more "modular" report and just be able to comment out parts of the report that I do not want to be generated with a single #\SweaveInput{part_x} rather than having to comment in or out entire blocks of code.
Recently I decided to move to R Markdown for multiple reasons being mainly practicality, the option of interactive (Shiny) integration in the report and the fact that I do not really need the extensive formatting options of LaTeX.
I found that technically pandoc is able to combine multiple Rmd files into one html output by just concatenating them but it would be nice if this behaviour could be called from a "master" Rmd file.
Any answer would be greatly appreciated even if it is just "go back to Sweave, it is not possible in Markdown".
I am using R 3.1.1 for Windows and Linux as well as Rstudio 0.98.1056 and Rstudio server 0.98.983.
Use something like this in the main document:
```{r child="CapsuleRInit.Rmd"}
```
```{r child="CapsuleTitle.Rmd", eval=TRUE}
```
```{r child="CapsuleBaseline.Rmd", eval=TRUE}
```
Use eval=FALSE to skip one child.
For RStudio users: you can define a main document for latex output, but this does not work for RMD documents, so you always have to switch to the main document for processing. Please support my feature request to RStudio; I tried already twice, but is seems to me that too few people use child docs to put it higher in the priority list.
I don't quite understand some of the terms in the answer above, but the solution relates to defining a custom knit: hook in the YAML header. For multipartite documents this allows you to, for example:
Have a 'main' or 'root' Rmarkdown file with an output: markdown_document YAML header
render all child documents from Rmd ⇒ md ahead of calling render, or not if this is time-limiting
combine multiple files (with the child code chunk option) into one (e.g. for chapters in a report)
write output: html_document (or other format) YAML headers for this compilation output on the fly, prepending to the markdown effectively writing a fresh Rmarkdown file
...then render this Rmarkdown to get the output, deleting intermediate files in the process if desired
The code for all of the above (dumped here) is described here, a post I wrote after working out the usage of custom knit: YAML header hooks recently (here).
The custom knit: function (i.e. the replacement to rmarkdown::render) in the above example is:
(function(inputFile, encoding) {
input.dir <- normalizePath(dirname(inputFile))
rmarkdown::render(input = inputFile, encoding = encoding, quiet=TRUE,
output_file = paste0(input.dir,'/Workbook-tmp.Rmd'))
sink("Workbook-compiled.Rmd")
cat(readLines(headerConn <- file("Workbook-header.yaml")), sep="\n")
close(headerConn)
cat(readLines(rmdConn <- file("Workbook-tmp.Rmd")), sep="\n")
close(rmdConn)
sink()
rmarkdown::render(input = paste0(input.dir,'/Workbook-compiled.Rmd'),
encoding = encoding, output_file = paste0(input.dir,'/../Workbook.html'))
unlink(paste0(input.dir,'/Workbook-tmp.Rmd'))
})
...but all squeezed onto 1 line!
The rest of the 'master'/'root'/'control' file or whatever you want to call it takes care of writing the aforementioned YAML for the final HTML output that goes via an intermediate Rmarkdown file, and its second code chunk programmatically appends child documents through a call to list.files()
```{r include=FALSE}
header.input.file <- "Workbook-header.yaml"
header.input.dir <- normalizePath(dirname(header.input.file))
fileConn <- file(header.input.file)
writeLines(c(
"---",
paste0('title: "', rmarkdown::metadata$title,'"'),
"output:",
" html_document:",
" toc: true",
" toc_depth: 3 # defaults to 3 anyway, but just for ease of modification",
" number_sections: TRUE",
paste0(" css: ",paste0(header.input.dir,'/../resources/workbook_style.css')),
' pandoc_args: ["--number-offset=1", "--atx-headers"]',
"---", sep="\n"),
fileConn)
close(fileConn)
```
```{r child = list.files(pattern = 'Notes-.*?\\.md')}
# Use file names with strict numeric ordering, e.g. Notes-001-Feb1.md
```
The directory structure would contain a top-level folder with
A final output Workbook.html
A resources subfolder containing workbook_style.css
A documents subfolder containing said main file "Workbook.Rmd" alongside files named as "Notes-001.Rmd", "Notes-002.Rmd" etc. (to ensure a fileglobbing on list.files(pattern = "Notes-.*?\\.Rmd) finds and thus makes them children in the correct order when rendering the main Workbook.Rmd file)
To get proper numbering of files, each constituent "Notes-XXX.Rmd" file should contain the following style YAML header:
---
title: "March: Doing x, y, and z"
knit: (function(inputFile, encoding) { input.dir <- normalizePath(dirname(inputFile)); rmarkdown::render(input = inputFile, encoding = encoding, quiet=TRUE)})
output:
md_document:
variant: markdown_github
pandoc_args: "--atx-headers"
---
```{r echo=FALSE, results='asis', comment=''}
cat("##", rmarkdown::metadata$title)
```
The code chunk at the top of the Rmarkdown document enters the YAML title as a second-level header when evaluated. results='asis' indicates to return plain text-string rather than
[1] "A text string"
You would knit each of these before knitting the main file - it's easier to remove the requirement to render all child documents and just append their pre-produced markdown output.
I've described all of this at the links above, but I thought it'd be bad manners not to leave the actual code with my answer.
I don't know how effective that RStudio feature request website may be... Personally I've not found it hard to look into the source code for these functions, which thankfully are open source, and if there really is something absent rather than undocumented an inner-workings-informed feature request is likely far more actionable by one of their software devs.
I'm not familiar with Sweave, was the above was what you were aiming at? If I understand correctly you just want to control the inclusion of documents in a modular fashion. The child = list.files() statement could take care of that: if not through file globbing you can straight-up list files as child = c("file1.md","file2md")... and switch that statement to change the children. You can also control TRUE/FALSE switches with YAML, whereby the presence of a custom header would set some children to be included for example
potentially.absent.variable: TRUE
...above the document with a silent include=FALSE hiding the machinations of the first chunk:
```{r include=FALSE}
!all(!as.logical(rmarkdown::metadata$potentially.absent.variable)
# ==> FALSE if potentially.absent.variable is absent
# ==> FALSE if anything other than TRUE
# ==> TRUE if TRUE
checkFor <- function(var) {
return !all(!as.logical(rmarkdown::metadata[[var]])
}
```
```{r child = "Optional_file.md", eval = checkFor(potentially.absent.variable)}
```

How to source R Markdown file like `source('myfile.r')`?

I often have a main R Markdown file or knitr LaTeX file where I source some other R file (e.g., for data processing). However, I was thinking that in some instances it would be beneficial to have these sourced files be their own reproducible documents (e.g., an R Markdown file that not only includes commands for data processing but also produces a reproducible document that explains the data processing decisions).
Thus, I would like to have a command like source('myfile.rmd') in my main R Markdown file. that would extract and source all the R code inside the R code chunks of myfile.rmd. Of course, this gives rise to an error.
The following command works:
```{r message=FALSE, results='hide'}
knit('myfile.rmd', tangle=TRUE)
source('myfile.R')
```
where results='hide' could be omitted if the output was desired. I.e., knitr outputs the R code from myfile.rmd into myfile.R.
However, it doesn't seem perfect:
it results in the creation of an extra file
it needs to appear in its own code chunk if control over the display is required.
It's not as elegant as simple source(...).
Thus my question:
Is there a more elegant way of sourcing the R code of an R Markdown file?
It seems you are looking for a one-liner. How about putting this in your .Rprofile?
ksource <- function(x, ...) {
library(knitr)
source(purl(x, output = tempfile()), ...)
}
However, I do not understand why you want to source() the code in the Rmd file itself. I mean knit() will run all the code in this document, and if you extract the code and run it in a chunk, all the code will be run twice when you knit() this document (you run yourself inside yourself). The two tasks should be separate.
If you really want to run all the code, RStudio has made this fairly easy: Ctrl + Shift + R. It basically calls purl() and source() behind the scene.
Factor the common code out into a separate R file, and then source that R file into each Rmd file you want it in.
so for example let's say I have two reports I need to make, Flu Outbreaks and Guns vs Butter Analysis. Naturally I'd create two Rmd documents and be done with it.
Now suppose boss comes along and wants to see the variations of Flu Outbreaks versus Butter prices (controlling for 9mm ammo).
Copying and pasting the code to analyze the reports into the new report is a bad idea for code reuse, etc.
I want it to look nice.
My solution was to factor the project into these files:
Flu.Rmd
flu_data_import.R
Guns_N_Butter.Rmd
guns_data_import.R
butter_data_import.R
within each Rmd file I'd have something like:
```{r include=FALSE}
source('flu_data_import.R')
```
The problem here is that we lose reproducibility. My solution to that is to create a common child document to include into each Rmd file. So at the end of every Rmd file I create, I add this:
```{r autodoc, child='autodoc.Rmd', eval=TRUE}
```
And, of course, autodoc.Rmd:
Source Data & Code
----------------------------
<div id="accordion-start"></div>
```{r sourcedata, echo=FALSE, results='asis', warnings=FALSE}
if(!exists(autodoc.skip.df)) {
autodoc.skip.df <- list()
}
#Generate the following table:
for (i in ls(.GlobalEnv)) {
if(!i %in% autodoc.skip.df) {
itm <- tryCatch(get(i), error=function(e) NA )
if(typeof(itm)=="list") {
if(is.data.frame(itm)) {
cat(sprintf("### %s\n", i))
print(xtable(itm), type="html", include.rownames=FALSE, html.table.attributes=sprintf("class='exportable' id='%s'", i))
}
}
}
}
```
### Source Code
```{r allsource, echo=FALSE, results='asis', warning=FALSE, cache=FALSE}
fns <- unique(c(compact(llply(.data=llply(.data=ls(all.names=TRUE), .fun=function(x) {a<-get(x); c(normalizePath(getSrcDirectory(a)),getSrcFilename(a))}), .fun=function(x) { if(length(x)>0) { x } } )), llply(names(sourced), function(x) c(normalizePath(dirname(x)), basename(x)))))
for (itm in fns) {
cat(sprintf("#### %s\n", itm[2]))
cat("\n```{r eval=FALSE}\n")
cat(paste(tryCatch(readLines(file.path(itm[1], itm[2])), error=function(e) sprintf("Could not read source file named %s", file.path(itm[1], itm[2]))), sep="\n", collapse="\n"))
cat("\n```\n")
}
```
<div id="accordion-stop"></div>
<script type="text/javascript">
```{r jqueryinclude, echo=FALSE, results='asis', warning=FALSE}
cat(readLines(url("http://code.jquery.com/jquery-1.9.1.min.js")), sep="\n")
```
</script>
<script type="text/javascript">
```{r tablesorterinclude, echo=FALSE, results='asis', warning=FALSE}
cat(readLines(url("http://tablesorter.com/__jquery.tablesorter.js")), sep="\n")
```
</script>
<script type="text/javascript">
```{r jqueryuiinclude, echo=FALSE, results='asis', warning=FALSE}
cat(readLines(url("http://code.jquery.com/ui/1.10.2/jquery-ui.min.js")), sep="\n")
```
</script>
<script type="text/javascript">
```{r table2csvinclude, echo=FALSE, results='asis', warning=FALSE}
cat(readLines(file.path(jspath, "table2csv.js")), sep="\n")
```
</script>
<script type="text/javascript">
$(document).ready(function() {
$('tr').has('th').wrap('<thead></thead>');
$('table').each(function() { $('thead', this).prependTo(this); } );
$('table').addClass('tablesorter');$('table').tablesorter();});
//need to put this before the accordion stuff because the panels being hidden makes table2csv return null data
$('table.exportable').each(function() {$(this).after('<a download="' + $(this).attr('id') + '.csv" href="data:application/csv;charset=utf-8,'+encodeURIComponent($(this).table2CSV({delivery:'value'}))+'">Download '+$(this).attr('id')+'</a>')});
$('#accordion-start').nextUntil('#accordion-stop').wrapAll("<div id='accordion'></div>");
$('#accordion > h3').each(function() { $(this).nextUntil('h3').wrapAll("<div>"); });
$( '#accordion' ).accordion({ heightStyle: "content", collapsible: true, active: false });
</script>
N.B., this is designed for the Rmd -> html workflow. This will be an ugly mess if you go with latex or anything else. This Rmd document looks through the global environment for all the source()'ed files and includes their source at the end of your document. It includes jquery ui, tablesorter, and sets the document up to use an accordion style to show/hide sourced files. It's a work in progress, but feel free to adapt it to your own uses.
Not a one-liner, I know. Hope it gives you some ideas at least :)
Try the purl function from knitr:
source(knitr::purl("myfile.rmd", quiet=TRUE))
Probably one should start thinking different. My issue is the following:
Write every code you normally would have had in a .Rmd chunk in a .R file.
And for the Rmd document you use to knit i.e. an html, you only have left
```{R Chunkname, Chunkoptions}
source(file.R)
```
This way you'll probably create a bunch of .R files and you lose the advantage of processing all the code "chunk after chunk" using ctrl+alt+n (or +c, but normally this does not work).
But, I read the book about reproducible research by Mr. Gandrud and realized, that he definitely uses knitr and .Rmd files solely for creating html files. The Main Analysis itself is an .R file.
I think .Rmd documents rapidly grow too large if you start doing your whole analysis inside.
If you are just after the code I think something along these lines should work:
Read the markdown/R file with readLines
Use grep to find the code chunks, searching for lines that start with <<< for example
Take subset of the object that contains the original lines to get only the code
Dump this to a temporary file using writeLines
Source this file into your R session
Wrapping this in a function should give you what you need.
The following hack worked fine for me:
library(readr)
library(stringr)
source_rmd <- function(file_path) {
stopifnot(is.character(file_path) && length(file_path) == 1)
.tmpfile <- tempfile(fileext = ".R")
.con <- file(.tmpfile)
on.exit(close(.con))
full_rmd <- read_file(file_path)
codes <- str_match_all(string = full_rmd, pattern = "```(?s)\\{r[^{}]*\\}\\s*\\n(.*?)```")
stopifnot(length(codes) == 1 && ncol(codes[[1]]) == 2)
codes <- paste(codes[[1]][, 2], collapse = "\n")
writeLines(codes, .con)
flush(.con)
cat(sprintf("R code extracted to tempfile: %s\nSourcing tempfile...", .tmpfile))
source(.tmpfile)
}
I use the following custom function
source_rmd <- function(rmd_file){
knitr::knit(rmd_file, output = tempfile())
}
source_rmd("munge_script.Rmd")
I would recommend keeping the main analysis and calculation code in .R file and importing the chunks as needed in .Rmd file. I have explained the process here.
sys.source("./your_script_file_name.R", envir = knitr::knit_global())
put this command before calling the functions contained in the your_script_file_name.R.
the "./" adding before your_script_file_name.R to show the direction to your file if you already created a Project.
You can see this link for more detail: https://bookdown.org/yihui/rmarkdown-cookbook/source-script.html
I use this one-liner:
```{r optional_chunklabel_for_yourfile_rmd, child = 'yourfile.Rmd'}
```
See:
My .Rmd file becomes very lengthy. Is that possible split it and source() it's smaller portions from main .Rmd?
I would say there is not a more elegant way of sourcing an Rmarkdown file. The ethos of Rmd being that the report is reproducible and at best will be self contained. However, adding to the OP's original solution, the below method avoids the permanent creation of the intermediate file on disk. It also makes some extra effort to ensure chunk output does not appear in the renderred document:
knit_loc <- tempfile(fileext = ".R")
knitr::knit("myfile.rmd",
output = knit_loc,
quiet = TRUE,
tangle = TRUE)
invisible(capture.output(source(knit_loc, verbose = FALSE)))
I would also add that if the child markdown dependencies are external to your R environment (eg write a file to disk, download some external resource, interact with a Web api etc), then instead of knit() I would opt for rmarkdown::render() instead:
rmarkdown::render("myfile.rmd")
this worked for me
source("myfile.r", echo = TRUE, keep.source = TRUE)
The answer by #qed is by far the best. Kevin Keena built the function proposed by #Paul Hiemstra, and this can help you to convert your .Rmd into an .R file to then source the code into another .R file, where knitr::purl would not be available.

Resources