I've run my analyses in a source Rmd file and would like to knit a clean version from a final Rmd file using only a few of the chunks from the source. I've seen a few answers with regard to pulling all of the chunks from a source Rmd in Source code from Rmd file within another Rmd and How to source R Markdown file like `source('myfile.r')`?. I share the concern with these posts in that I don't want to port out a separate .R file, which seems to be the only way that read_chunk works.
I think I'm at the point where I can import the source Rmd, but now I'm not sure how to call specific chunks from it in the final Rmd. Here's a reproducible example:
SourceCode.Rmd
---
title: "Source Code"
output:
pdf_document:
latex_engine: xelatex
---
```{r}
# Load libraries
library(knitr) # Create tables
library(kableExtra) # Table formatting
# Create a dataframe
df <- data.frame(x = 1:10,
y = 11:20,
z = 21:30)
```
Some explanatory text
```{r table1}
# Potentially big block of stuff I don't want to have to copy/paste
# But I want it in the final document
kable(df, booktabs=TRUE,
caption="Big long title for whatever") %>%
kable_styling(latex_options=c("striped","HOLD_position")) %>%
column_spec(1, width="5cm") %>%
column_spec(2, width="2cm") %>%
column_spec(3, width="3cm")
```
[Some other text, plus a bunch of other chunks I don't need for anyone to see in the clean version.]
```{r}
save(df, file="Source.Rdata")
```
FinalDoc.Rmd
---
title: "Final Doc"
output:
pdf_document:
latex_engine: xelatex
---
```{r setup, include=FALSE}
# Load libraries and data
library(knitr) # Create tables
library(kableExtra) # Table formatting
opts_chunk$set(echo = FALSE)
load("Source.Rdata")
```
As far as I can tell, this is likely the best way to load up SourceCode.Rmd (from the first linked source above):
```{r}
options(knitr.duplicate.label = 'allow')
source_rmd2 <- function(file, local = FALSE, ...){
options(knitr.duplicate.label = 'allow')
tempR <- tempfile(tmpdir = ".", fileext = ".R")
on.exit(unlink(tempR))
knitr::purl(file, output=tempR, quiet = TRUE)
envir <- globalenv()
source(tempR, local = envir, ...)
}
source_rmd2("SourceCode.Rmd")
```
At this point, I'm at a loss as to how to call the specific chunk table1 from SourceCode.Rmd. I've tried the following as per instructions here with no success:
```{r table1}
```
```{r}
<<table1>>
```
The first seems to do nothing, and the second throws an unexpected input in "<<" error.
I wrote a function source_rmd_chunks() that sources chunk(s) by label name. See gist.
Related
I am making my code more modular and would like to run multiple RMarkdown files from one overall RMarkdown. I believe I could do this if I translated all my RMarkdown files to .R scripts and used source(), but I like the document-like nature of RMarkdown and I can describe what I'm doing as I'm doing it in plain text.
The goal is to wrangle data and export a usable .sav file. I want to run clean.rmd from run.rmd, but I don't want any HTML/pdf/etc. output. Removing the output line in the YAML header doesn't prevent output. If there is a way to do this without translating everything to .R scripts, I would be very appreciative. Thank you.
clean.rmd: Script that does the cleaning
---
title: "clean"
author: "jrcalabrese"
date: "12/30/2021"
output: html_document
---
```{r}
library(tidyverse)
library(haven)
```
```{r}
data(cars)
cars <- cars %>%
mutate(newvar = speed + dist)
```
```{r}
write_spss(cars, "~/Documents/cars_new.sav", compress = FALSE)
```
run.rmd: Script that runs clean.rmd
---
title: "run"
author: "jrcalabrese"
date: "12/30/2021"
output: html_document
---
```{r}
rmarkdown::render("~/Documents/clean.rmd")
```
Thank you for your help! This function works:
---
title: "run"
author: "jrcalabrese"
date: "12/30/2021"
#output: html_document
---
```{r}
source_rmd = function(file, ...) {
tmp_file = tempfile(fileext=".R")
on.exit(unlink(tmp_file), add = TRUE)
knitr::purl(file, output=tmp_file)
source(file = tmp_file, ...)
}
```
```{r}
source_rmd("~/Documents/clean.rmd")
```
Good morning everybody,
as stated above, I’m trying to render multiple Rmarkdown reports with different parameters for each report. Basically I have a folder of .csv files, which I have to clean up. I have packed all the steps in an .Rmd file, because this way the data gets cleaned and a short report is generated documenting the results. Some figures, some stats, nothing very dramatic, just an overview of how the cleaning went.
As each .csv file is slightly different, I have to tweak some parameters. This is the easy part. I have found some nice code in the “R for Data Science” book, which you can find here. https://r4ds.had.co.nz/r-markdown.html#parameters
This is my version:
library(dplyr)
library(stringr)
library(purrr)
# Create a vector with names
files <- c("dataframe", "datatable")
# Create a tibble with filenames and lists of parameters
reports <- tibble(
filename = str_c(files, ".html"),
params = map(files, ~ list(name = .,
factor = if_else(. == "dataframe", 2.5, 5))))
#-------------------------------------------------------------------
# make reports
reports <- reports %>%
select(output_file = filename, params) %>%
purrr::pwalk(rmarkdown::render, input = "template_datatable.Rmd")
Everything runs fine, when the .Rmd file uses data.frames.
As my .csv are about 1 GB each, I would use data.table to speed things up. But as soon as my .Rmd file contains some data.table code I get this error message:
Error: `:=` can only be used within a quasiquoted argument
If I just render one file with rmarkdown::render(input = "template_datatable.Rmd", output_file = "test.html", params = list(name = "datatable", carat = 5)), the .Rmd with the data.table code works fine.
My questions are.
What is causing this error? And is there a way to fix it?
Here is my code for the .Rmd using data.frames:
---
title: "A report for `r params$name`"
params:
name: "name"
factor: 1
output:
bookdown::html_document2:
fig_caption: yes
toc: yes
toc_float: true
code_folding: "hide"
---
```{r setup, include=FALSE}
# Setup Chunk
# Some knitr options
knitr::opts_chunk$set(echo = FALSE)
# Packages
library(dplyr)
library(ggplot2)
```
```{r dataImport}
df <- data.frame(A = seq(1, 100), B = seq(1, 100))
df <- df %>%
mutate(C = B * params$factor)
```
```{r makePlot}
ggplot(df, aes(A, C)) +
geom_line()
```
And my code for the .Rmd using data.tables:
```
---
title: "A report for `r params$name`"
params:
name: "name"
factor: 1
output:
bookdown::html_document2:
fig_caption: yes
toc: yes
toc_float: true
code_folding: "hide"
---
```{r setup, include=FALSE}
# Setup Chunk
# Some knitr options
knitr::opts_chunk$set(echo = FALSE)
# Packages
library(data.table)
library(ggplot2)
```
```{r dataImport}
dt <- data.table(A = seq(1, 100), B = seq(1, 100))
dt <- dt[, C := B*params$factor]
```
```{r makePlot}
ggplot(dt, aes(A, C)) +
geom_line()
```
Thanks for your help.
I am having a problem with my ztable,
I want to knit my Rmarkdown file to HTML but I cannot find a way to display the table I created with ztable:
z=ztable(loucaste) %>% makeHeatmap(palette = "Blues") %>% print(caption="Table 2.)
I tried to set
options(ztable.table="html")
and put this at the beginning as I read somewhere else
output: html_document
header-includes: \usepackage{colortbl}
but it doesn't work when I knit to HTML. My intention was to create a sort of formatting table similar to the ones made on excel and ztable looks like the only way.
Try this minimal Rmd. The key seems to be options(ztable.type = "html") and in the chunk that generates the table, r results='asis'
If that works for you, substitute your code in the appropriate place i.e. ztable(loucaste) %>% makeHeatmap(palette = "Blues") %>% print(caption="Table 2.).
---
title: "ztable"
output: html_document
---
```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = TRUE)
library(ztable)
library(magrittr)
options(ztable.type = "html")
```
## R Markdown
```{r results='asis'}
matrix(1:100, nrow = 10) %>%
as.data.frame() %>%
ztable() %>%
makeHeatmap() %>%
print(caption = "table 2")
```
I have an R Markdown table with this \rule{1cm}{0.4pt} LaTeX command in each cell of one column. The table formats just fine with kable if I do not include the kableExtra package. If I do include kabelExtra, the LaTeX command is no longer interpreted. The results are shown below, without and with kableExtra. No other change was made. The top example is my desired result.
I inspected the .tex output. kableExtra seems to format the LaTeX command as literal text: \textbackslash{}rule\{1cm\}\{0.4pt\} instead of the command shown above.
I want to use kableExtra for other features like setting column widths but I need it to interpret the LaTeX commands. I did not find anything in the manual or vignettes that seemed to address included LateX commands. Am I missing something?
Edit
I tried adding format = "latex" to the kable call when using kableExtra but undesired result remained.
MWE
---
title: "Without kableExtra"
output:
pdf_document:
keep_tex: TRUE
---
```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = TRUE)
```
```{r}
library(tibble)
library(knitr)
#library(kableExtra)
a = seq(1:3)
b = seq(4:6)
tab <- as.tibble(cbind(a,b))
tab <- add_column(tab, c = "\\rule{1cm}{0.4pt}")
```
```{r}
kable(tab,
booktabs = TRUE,
longtable = TRUE)
```
Results
When using kableExtra you should add the argument escape = FALSE to your kable() call. The escape argument let you use LaTeX commands in table.
The following works:
---
title: "Without kableExtra"
output:
pdf_document:
keep_tex: TRUE
---
```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = TRUE)
```
```{r}
library(tibble)
library(knitr)
library(kableExtra)
a = seq(1:3)
b = seq(4:6)
tab <- as.tibble(cbind(a,b))
tab <- add_column(tab, c = "\\rule{1cm}{0.4pt}")
```
```{r}
kable(tab,
booktabs = TRUE,
longtable = TRUE,
escape = FALSE)
```
I am knitting a .Rmd file and want to have two outputs: the html and a purl'ed R script each time I run knit. This can be done with the following Rmd file:
---
title: "Purl MWE"
output: html_document
---
```{r}
## This chunk automatically generates a text .R version of this script when running within knitr.
input = knitr::current_input() # filename of input document
output = paste(tools::file_path_sans_ext(input), 'R', sep = '.')
knitr::purl(input,output,documentation=1,quiet=T)
```
```{r}
x=1
x
```
If you do not name the chunk, it works fine and you get html and .R output each time you run knit() (or click knit in RStudio).
However, if you name the chunk it fails. For example:
title: "Purl MWE"
output: html_document
---
```{r}
## This chunk automatically generates a text .R version of this script when running within knitr.
input = knitr::current_input() # filename of input document
output = paste(tools::file_path_sans_ext(input), 'R', sep = '.')
knitr::purl(input,output,documentation=1,quiet=T)
```
```{r test}
x=1
x
```
It fails with:
Quitting from lines 7-14 (Purl.Rmd)
Error in parse_block(g[-1], g[1], params.src) : duplicate label 'test'
Calls: <Anonymous> ... process_file -> split_file -> lapply -> FUN -> parse_block
Execution halted
If you comment out the purl() call, it will work with the named chunk. So there is something about how the purl() call is also naming chunks which causes knit() to think there are duplicate chunk names even when there are no duplicates.
Is there a way to include a purl() command inside a .Rmd file so both outputs (html and R) are produced? Or is there a better way to do this? My ultimate goal is to use the new rmarkdown::render_site() to build a website that updates the HTML and R output each time the site is compiled.
You can allow duplicate labels by including options(knitr.duplicate.label = 'allow') within the file as follows:
title: "Purl MWE"
output: html_document
---
```{r GlobalOptions}
options(knitr.duplicate.label = 'allow')
```
```{r}
## This chunk automatically generates a text .R version of this script when running within knitr.
input = knitr::current_input() # filename of input document
output = paste(tools::file_path_sans_ext(input), 'R', sep = '.')
knitr::purl(input,output,documentation=1,quiet=T)
```
```{r test}
x=1
x
```
This code isn't documented on the knitr website, but you can keep track with the latest changes direct from Github: https://github.com/yihui/knitr/blob/master/NEWS.md
A related approach to #ruaridhw solution would be to wrap the knitr::purl() in callr::r(). See function below that saves the R chunks from a specified R markdown file to a temporary .R file:
# RMD to local R temp file
# inspiration: https://gist.github.com/noamross/a549ee50e8a4fd68b8b1
rmd_chunks_to_r_temp <- function(file){
temp <- tempfile(fileext=".R")
# needed callr so can use when knitting -- else can bump into "duplicate chunk
# label" errors when running when knitting
callr::r(function(file, temp){
knitr::purl(file, output = temp)
},
args = list(file, temp))
}
This function also exists in funspotr:::rmd_chunks_to_r_temp() at brshallo/funspotr.
You can avoid this error with a bash chunk that calls purl in a separate R session. That way there's no need to allow duplicate labels.
An example use case is an Rmd file where the code is run (and not echo'd) throughout the report and then all the code chunks are shown with chunks names and code comments in an Appendix. If you don't require that additional functionality then you would only need up until the bash chunk.
The idea is that report_end signifies where to stop purl such that the appendix code isn't considered "report code". Then read_chunk reads the entire R file into one code chunk which can then be echo'd with syntax highlighting if required.
---
title: "Purl MWE"
output: html_document
---
These code chunks are used in the background of the report however
their source is not shown until the Appendix.
```{r test1, echo=FALSE}
x <- 1
x
```
```{r test2, echo=FALSE}
x <- x + 1
x
```
```{r test3, echo=FALSE}
x <- x + 1
x
```
# Appendix
```{r, eval=TRUE}
report_end <- "^# Appendix"
temp <- tempfile(fileext = ".R")
Sys.setenv(PURL_IN = shQuote("this_file.Rmd"), # eg. knitr::current_input()
PURL_OUT = shQuote(temp),
PURL_END = shQuote(report_end))
```
```{bash, include=FALSE}
Rscript -e "lines <- readLines($PURL_IN, warn = FALSE)" \
-e "knitr::purl(text = lines[1:grep($PURL_END, lines)], output = $PURL_OUT, documentation = 1L)"
```
```{r, include=FALSE}
knitr::read_chunk(temp, labels = "appendix")
unlink(temp)
```
```{r appendix, eval=FALSE, echo=TRUE}
```