Similar to how to create a loop that includes both a code chunk and text with knitr in R i try to get text and a Code snippet created by a Loop.
Something along this:
---
title: Sample
output: html_document
params:
test_data: list("x <- 2", "x <- 4")
---
for(nr in 1:3){
cat(paste0("## Heading ", nr))
```{r, results='asis', eval = FALSE, echo = TRUE}
params$test_data[[nr]]
```
}
Expected Output would be:
What i tried:
I tried to follow: https://stackoverflow.com/a/36381976/8538074. But printing "```" did not work for me.
You can make use of knitr hooks. Take the following MRE:
---
title: "Untitled"
output: html_document
params:
test_data: c("x <- 2", "x <- 4")
---
```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = TRUE)
```
```{r, results = 'asis', echo = F}
hook <- knitr::hooks_html()$source
opts <- knitr::opts_chunk$get()
chunks <- eval(parse(text = params$test_data))
for(nr in seq_along(chunks)){
cat(paste0("## Heading ", nr, "\n"))
cat(hook(chunks[nr], options = opts))
}
```
We get the default source hook and also the default chunk options. Then we get the test data, which is supplied as a string. Therefore we parse and evaluate that string.
In the loop we simply call the source hook on each element of the test data. Here is the result:
Related
I try to create Code snippet programmatically through a provided Parameter but Keep the target programming language dynamic.
What i tried:
Following https://stackoverflow.com/a/64855295/8538074
i know i could use opts <- knitr::opts_chunk$get()
which will include an engine opts$engine which could be tried
to bet set to "SQL".
I guess that sthg like that should work because of:
https://github.com/yihui/knitr-examples/blob/master/115-engine-sql.md
https://github.com/yihui/knitr-examples/blob/master/115-engine-sql.Rmd
(but i would need to render it from code since i handover the corresponding code string via the params of the rmarkdown file)
My best try:
---
title: "xx"
output: html_document
params:
code: list(language = "SQL", code_string = "SELECt * FROM tbl LIMIT 15")
---
```{r setup, include=FALSE}
hook <- knitr::hooks_html()$source
opts <- knitr::opts_chunk$get()
language <- params$code$code$language
opts$engine <- language
code_string <- params$code$code_string
cat(hook(code_string, options = opts))
```
Based on MartinĀ“s comment:
---
title: "xx"
output: html_document
params:
code: list(language = "SQL", code_string = "SELECT * FROM tbl LIMIT 15")
---
```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = TRUE)
```
```{r, results = 'asis', echo = F}
chunks <- eval(parse(text = params$code))
hook <- knitr::hooks_html()$source
opts <- knitr::opts_chunk$get()
opts$highlight <- FALSE
code_string <- chunks$code_string
cat(hook(code_string, options = opts))
```
When I render an RMD automatically calling rmarkdown::render() within an R-Script, I run into trouble when - within the RMD itself - I try to access list-variables. In the example I want to loop through the content of the list variable and render a table for each list.
The first chunk
# This works
```{r, echo = FALSE, results='show'}
knitr::kable(a[[1]])
```
within the RMD renders successfully. However, the second section chunk
# This doesn't work
```{r, echo = FALSE, results='show'}
for (i in 1:length(a)) {
knitr::kable(a[[i]])
}
doesn't evaluate at all. There is not even an error/warning. The complete output renders as follows:
How can I successfully render the second chunk, named 'This doesn't work'? I'd expect to see 3 lists here, displaying the numbers 1:10, 11:20, 21:30.
Reproducible example: Save the following script as render.R:
setwd("C:/path_to_your_script_location/")
# generate a list containing 3 lists
a <- list(list(tour_id=1:10), list(tour_id=11:20), list(tour_id=21:30))
rmarkdown::render("test.Rmd", output_dir = "./", output_file = "out_test.html",
encoding = "UTF-8", quiet = TRUE)
and save the following content as test.Rmd:
---
title: Test
author: "Author"
date: "May 9th, 2018"
output: html_document
---
# This works
```{r, echo = FALSE, results='show'}
knitr::kable(a[[1]])
```
# This doesn't work
```{r, echo = FALSE, results='show'}
for (i in 1:length(a)) {
knitr::kable(a[[i]])
}
```
My solution: Change your last chunk to
```{r, echo = FALSE, results='asis'}
for (i in 1:length(a)) {
print(knitr::kable(a[[i]]))
}
```
I am currently writing on a report with rmarkdown and therefore I want to create sections inside a r code chunk. I figured out that this is possible with the help of cat() and results="asis". My problem with this solution is, that my R code results and code isn't properly displayed as usual.
For example
---
title: "test"
output: pdf_document
---
```{r, results='asis'}
for (i in 1:10) {
cat("\\section{Part:", i, "}")
summary(X)
$\alpha = `r X[1,i]`$
}
```
pretty much does the trick, but here there are still two problems:
the R output for summary() is displayed very strange because I guess it`s interpreted as LaTeX code
I can't use LaTeX formulas in this enviroment, so if I want every section to end with a equation, which also might use a R variable, this is not possible
Does somebody know a solution for some of these problems, or is there even a workaround to create sections within a loop and to have R code, R output and LaTeX formulas in this section? Or maybe at least one of those things?
I am very thankful for every kind of advice
You can do what you are after inline without relying as much on code blocks.
As a minimal example.
---
title: "test"
output: pdf_document
---
```{r sect1_prep, include=FALSE}
i <- 1
```
\section{`r paste0("Part: ", i)`}
```{r sect1_body}
summary(mtcars[, i])
```
$\alpha = `r mtcars[1, i]`$
```{r sect2_prep, include=FALSE}
i <- i + 1
```
\section{`r paste0("Part: ", i)`}
```{r sect2_body}
summary(mtcars[, i])
```
$\alpha = `r mtcars[1, i]`$
Produces...
If you really want to have a section factory, you could consider pander.
---
title: "test"
output: pdf_document
---
```{r setup, include=FALSE}
library(pander)
panderOptions('knitr.auto.asis', FALSE)
```
```{r, results='asis', echo=FALSE}
empty <- lapply(1:10, function(x) {
pandoc.header(paste0("Part: ", x), level = 2)
pander(summary(mtcars[, x]))
pander(paste0("$\\alpha = ", mtcars[1, x], "$\n"))
})
```
which produces...
remove summary table format example
---
title: "test"
output: pdf_document
---
```{r setup, include=FALSE}
library(pander)
panderOptions('knitr.auto.asis', FALSE)
```
```{r, results='asis', echo=FALSE}
content <- lapply(1:10, function(x) {
head <- pandoc.header.return(paste0("Part: ", x), level = 2)
body1 <- pandoc.verbatim.return(attr(summary(mtcars[, x]), "names"))
body2 <- pandoc.verbatim.return(summary(mtcars[, x]))
eqn <- pander_return(paste0("$\\alpha = ", mtcars[1, x], "$"))
return(list(head = head, body1 = body1, body2 = body2, eqn = eqn))
})
writeLines(unlist(content), sep = "\n\n")
```
I am printing an r markdown file to pdf. I've tried various output specifications, but the plot keeps displaying in the middle of segments [1] and [2].
I want the all of the code to be displayed one chunk, and will call the plot later in the document.
```{r, include=TRUE, results='hide'}
# [1] There is code up here
# [plot interrupts the code chunk here] Scatter plot
plot1 = plot(df$var1, df$var)
# [2] More code below this point
```
Use the chunk option fig.show = 'hold' to display all the plots produced by a chunk at the end of the chunk. Here is an example .Rmd file and output.
---
title: Stop Plot Breakikng Up Code Chunk
output: pdf_document
---
The key is to use the chunk option `fig.show = 'hold'` so that all plots from
the chunk will will displayed at the end of the chunk.
```{r setup, include = FALSE, cache = FALSE}
library(knitr)
opts_chunk$set(fig.show = "hold")
```
We'll use the `mtcars` data set for the example.
```{r plot1, include = TRUE, results = "hide"}
mean(mtcars$wt)
mean(mtcars$mpg)
plot(mtcars$wt, mtcars$mpg)
var(mtcars$wt)
```
End of example.
EDIT:
Another solution, closer to what I think you are looking for, is to use ref.label to reuse code chunks.
---
title: Stop Plot Breaking Up Code Chunk
output: pdf_document
---
The key is to use the chunk option `fig.show = 'hold'` so that all plots from
the chunk will will displayed at the end of the chunk.
```{r setup, include = FALSE, cache = FALSE}
library(knitr)
opts_chunk$set(fig.show = "hold",
collapse = TRUE)
```
We will use the `mtcars` data set for the example.
```{r all_code}
```{r mean_code, ref.label = "means", echo = TRUE, results = "hide"}
```{r plot1_code, ref.label = "plot1", echo = TRUE, fig.show = "hide", fig.keep = "none"}
```{r var_code, ref.label = "var_wt", echo = TRUE, results = "hide"}
```
Description of a plot
```{r "plot1", echo = FALSE}
plot(mtcars$wt, mtcars$mpg)
```
More text.
Below here, chunks that are evaluated, but not shown.
```{r means, include = FALSE}
mean(mtcars$wt)
mean(mtcars$mpg)
```
```{r var_wt, include = FALSE}
var(mtcars$wt)
```
End of the example.
You can write 2 chunks :
## Title
Herebelow the code are not separated by plots :
```{r display_code_only, eval=FALSE}
plot(pressure)
plot(iris)
```
Herebelow the plot are not separated by code :
```{r display_plot_only, echo=FALSE}
plot(pressure)
plot(iris)
```
The following code is a very simplified MRE for an issue I'm experiencing. I'm trying to avoid R template packages, such as brew, and only use knit_expand() to achieve my goals. The issue is twofold:
generated chunks don't get parsed (this is not happening in my real code, but happens in MRE)
instead of LaTeX \includegraphics, knitr (or rmarkdown, or pandoc) generates RMarkdown syntax for inserting figures (![]).
In regard to the former, I have a feeling that it might be related to my incorrect use of get() or its argument. Your advice would be very much appreciated. The MRE follows ('.Rmd' document):
---
title: "MRE: a dynamic chunk issue"
author: "Aleksandr Blekh"
output:
pdf_document:
fig_caption: yes
keep_tex: yes
highlight: NULL
---
```{r, echo=FALSE, include=FALSE}
library(knitr)
opts_knit$set(progress = F, verbose = F)
opts_chunk$set(comment=NA, warning=FALSE, message=FALSE, echo=FALSE, tidy=FALSE)
```
```{r Preparation, results='hide'}
g1 <- plot(cars)
g2 <- plot(iris$Sepal.Length)
myPlots <- list(g1, g2)
bcRefStr <- list("objType" = "fig",
"objs" = c("g1", "g2"),
"str" = "Plots \\ref{fig:g1} and \\ref{fig:g2}")
```
```{r DynamicChunk, include=FALSE}
chunkName <- "{{name}}"
chunkHeader <- paste0("```{r ", chunkName, ", ")
chunkOptions <- "include=TRUE, results='asis', fig.height=4, fig.width=4, fig.cap='{{name}}'"
chunkHeaderFull <- paste0(chunkHeader, chunkOptions, "}")
chunkBody <- "print(get('{{name}}'))"
latexFigEnvBegin <- "cat('\\\\begin{figure}')"
latexFigEnvEnd <- "cat('\\\\end{figure}')"
latexFigCenter <- "cat('\\\\centering')"
latexObjLabel <- paste0("cat('\\\\caption{\\\\ ", "{{name}}\\\\label{", bcRefStr$objType, ":{{name}}", "}}')")
chunkText <- c(chunkHeaderFull,
latexFigEnvBegin, latexFigCenter,
chunkBody,
latexObjLabel, latexFigEnvEnd,
"```", "\n")
figReportParts <- lapply(bcRefStr$objs, function (x) knit_expand(text = chunkText, name = x))
```
`r knit(text = unlist(figReportParts))`
Finally, I've figured out what was causing the issue. The first part was easy. Due to suggested simplification, I've switched from ggplot2 to standard R graphics functions. The problem is that it appears that plot() doesn't return a value/object, so that's why NULLs has been seen in the output, instead of plots.
The second part was a bit more tricky, but an answer to a related question (https://stackoverflow.com/a/24087398/2872891) clarified the situation. Based on that information, I was able modify my MRE correspondingly and the resulting document appears with correct content (same applies to the generated LaTeX source, which seems to be ready for cross-referencing).
I'm thinking about converting this code into a more generic function for reuse across my project, if time will permit [shouldn't take long] (#Yihui, could this be useful for knitr project?). Thanks to everyone who took time to analyze, help or just read this question. I think that knitr's documentation should be more clear on issues, related to producing PDF documents from RMarkdown source. My solution for the MRE follows.
---
title: "MRE: a dynamic chunk issue"
author: "Aleksandr Blekh"
output:
pdf_document:
fig_caption: yes
keep_tex: yes
highlight: NULL
---
```{r, echo=FALSE, include=FALSE}
library(knitr)
library(ggplot2)
opts_knit$set(progress = F, verbose = F)
opts_chunk$set(comment=NA, warning=FALSE, message=FALSE, echo=FALSE, tidy=FALSE)
```
```{r Preparation, results='hide'}
library(ggplot2)
g1 <- qplot(mpg, wt, data=mtcars)
g2 <- qplot(mpg, hp, data=mtcars)
myPlots <- list(g1, g2)
bcRefStr <- list("objType" = "fig",
"objs" = c("g1", "g2"),
"str" = "Plots \\ref{fig:g1} and \\ref{fig:g2}")
```
```{r DynamicChunk, include=FALSE}
latexObjLabel <- paste0("{{name}}\\\\label{", bcRefStr$objType, ":{{name}}", "}")
chunkName <- "{{name}}"
chunkHeader <- paste0("```{r ", chunkName, ", ")
chunkOptions <- paste0("include=TRUE, results='asis', fig.height=4, fig.width=4, fig.cap='", latexObjLabel, "'")
chunkHeaderFull <- paste0(chunkHeader, chunkOptions, "}")
chunkBody <- "print(get('{{name}}'))"
chunkText <- c(chunkHeaderFull,
chunkBody,
"```", "\n")
figReportParts <- lapply(bcRefStr$objs, function (x) knit_expand(text = chunkText, name = x))
```
`r knit(text = unlist(figReportParts))`