How to avoid figure filenames in child calls - r

I would like to reuse a child file from my parent Rmd after modifying my data. The code seems to work fine, but the first figures are stepped over and all figures are replaced by the last one.
Is there a way to force new filenames with each new call?
This is my Parent.Rmd
XParent
========
```{r Opts, echo=FALSE}
opts_chunk$set(fig.show='asis', fig.keep='all', fig.width=3, fig.height=4, options(digits = 2), dev='jpeg')
```
```{r XLoad}
read_chunk(lines = readLines('XCode.R'))
```
```{r ParentChunk}
```
First child call
---------------
#### NOTICE the data is OK but the figure corresponds to the second child call (Y axis = 1200)
```{r CallChild, child='XChild.Rmd'}
```
#### I now modify the dataframe
```{r}
df$dist <- df$dist * 10
```
Second child call
-----------------
As this is the last case, the figure agrees with the data:
```{r CallChild2, child='XChild.Rmd'}
```
This Child.Rmd
XChild
```{r CodeAndFigs}
```
and XCode.R
## #knitr ParentChunk
df <- cars
colMeans(df)
# Y axis' upper limit is 120
plot(cars)
## #knitr CodeAndFigs
colMeans(df)
plot(df)
The figure in the first child call has been replace by the second figure. I have tried playing with different fig.keep and fig.show options with no luck.

With the latest development version on Github (which will turn into knitr 1.3 very soon on CRAN), you can use the fig.path option to specify different figure paths for the child document in two parent chunks CallChild and CallChild2, e.g.
XParent
========
```{r Opts, echo=FALSE}
opts_chunk$set(fig.show='asis', fig.keep='all', fig.width=3, fig.height=4, options(digits = 2), dev='jpeg')
```
```{r XLoad}
read_chunk(lines = readLines('XCode.R'))
```
```{r ParentChunk}
```
First child call
---------------
#### NOTICE the data is OK but the figure corresponds to the second child call (Y axis = 1200)
```{r CallChild, child='XChild.Rmd', fig.path='figure/child-'}
```
#### I now modify the dataframe
```{r}
df$dist <- df$dist * 10
```
Second child call
-----------------
As this is the last case, the figure agrees with the data:
```{r CallChild2, child='XChild.Rmd', fig.path='figure/child2-'}
```
The child document will inherit options from its parent chunk, so the figure paths will no clash if the parent options are different.

Related

rmarkdown/purrr: remove list indices between plots

When I knit a document containing multiple plots obtained through purrr:map function, I get text slides in between each plot slide containing unwanted list index information (see image slides 2, 4, and 6). I'd like to remove these and just have plots.
I've tried results = "hide" and results = FALSE in the header.
These just return one plot instead of many, AND the text is still
there.
I've tried adding invisible() around my code as recommended
here. I don't see a difference.
How can I remove these and just have three slides with the three plots with no text?
---
title: "Reprex"
output: powerpoint_presentation
---
```{r include=FALSE}
library(tidyverse)
```
```{r echo=FALSE, results = FALSE}
ys <- c("mpg","cyl","disp")
ys %>% map(function(y)
invisible(ggplot(mtcars, aes(hp)) + geom_point(aes_string(y=y))))
```
Try this:
To suppress the console output use purrr::walk instead of map. See e.g. https://chrisbeeley.net/?p=1198
To get each plot printed on a separate slide use results='asis' and add two newlines via cat('\n\n') after each plot.
---
title: "Reprex"
output: powerpoint_presentation
---
```{r include=FALSE}
library(tidyverse)
```
```{r echo=FALSE, results='asis'}
ys <- c("mpg","cyl","disp")
walk(ys, function(y) {
p <- ggplot(mtcars, aes(hp)) + geom_point(aes_string(y=y))
print(p)
cat('\n\n')
})
```

Dynamic plots and tables inside Rmarkdown

I am new to Rmarkdown and shiny and forgive me for some naive questions. I have build a code in two parts first where I do all the processing and second where I call the Rmarkdown to knit it.
The first code example.R is as follows and works fine independently (with only glitch of plots being trimmed from sides):
# Create a label for the knitr code chunk name
## #knitr ExternalCodeChunk020
library(Seurat)
library(tidyverse)
library(sleepwalk)
library(gridExtra)
library(plotly)
library(DT)
# Set up some sample data
data(mtcars)
# Display the xvars
# Note that I don't really want to display the xvars, but this line is included
# to demonstrate that text output won't show up in the RMarkdown in this example.
a <- ggplotly(ggplot(mtcars, aes(cyl,mpg)) + geom_boxplot())
b <- ggplotly(ggplot(mtcars, aes(wt,mpg)) + geom_point())
subplot(a, b, nrows=1)
DT::datatable(mtcars, class = "cell-border stripe", rownames = FALSE, filter ="top",
editable =TRUE, extension = "Buttons", options = list(dom="Bfrtip",
buttons =c("copy", "csv", "excel", "pdf","print")))
ggplotly(ggplot(mtcars,aes(x=mpg)) + geom_histogram(binwidth=5))
# Display the date and time
# Similar to xvars above, this line is intended to demonstrate that text output
# won't be displayed in this RMarkdown example.
Sys.Date()
The second part of the code (mrkdwn.Rmd) is where I try to knit and generate Rmarkdown report:
---
title: "Code Chunks"
author: "Author"
date: "November 13, 2020"
output: html_document
---
```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = TRUE)
knitr::read_chunk("example.R")
```
This first code chunk prints the externally located code,
but it does not execute the code. The next code chunk
executes the externally located code, but it does not print code
itself. Text output is suppressed, and figures are plotted,
but only after all of the code is executed.
```{r DisplayCodeChunk, eval = FALSE, echo = FALSE}
<<ExternalCodeChunk020>>
```
```{r RunCodeChunk, echo = FALSE, eval = TRUE, results = 'hide'}
<<ExternalCodeChunk020>>
```
the output doesn't contain plots. I am not sure what is going wrong, could anyone of you help me in fixing this.
I know that an easy fix is to put both parts of the code together inside the Rmarkdown like this:
---
title: "test3"
output: html_document
---
```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = TRUE)
```
## R Markdown
This is an R Markdown document. Markdown is a simple formatting syntax for authoring HTML, PDF, and MS Word documents. For more details on using R Markdown see <http://rmarkdown.rstudio.com>.
When you click the **Knit** button a document will be generated that includes both content as well as the output of any embedded R code chunks within the document. You can embed an R code chunk like this:
```{r}
library(Seurat)
library(tidyverse)
library(sleepwalk)
library(gridExtra)
library(plotly)
library(DT)
# Set up some sample data
data(mtcars)
# Display the xvars
# Note that I don't really want to display the xvars, but this line is included
# to demonstrate that text output won't show up in the RMarkdown in this example.
a <- ggplotly(ggplot(mtcars, aes(cyl,mpg)) + geom_boxplot())
b <- ggplotly(ggplot(mtcars, aes(wt,mpg)) + geom_point())
subplot(a, b, nrows=1)
DT::datatable(mtcars, class = "cell-border stripe", rownames = FALSE, filter ="top",
editable =TRUE, extension = "Buttons", options = list(dom="Bfrtip",
buttons =c("copy", "csv", "excel", "pdf","print")))
ggplotly(ggplot(mtcars,aes(x=mpg)) + geom_histogram(binwidth=5))
# Display the date and time
# Similar to xvars above, this line is intended to demonstrate that text output
# won't be displayed in this RMarkdown example.
Sys.Date()
```
## Including Plots
You can also embed plots, for example:
```{r pressure, echo=FALSE}
plot(pressure)
```
Since I need to process large datasets and generate graphs/plots and table I would prefer to keep them separately, so that my Rmarkdown doesn't crash. May be this is wrong and there could be a better approach, please suggest.
Many thanks for your time and help.

How do I parameterize template blocks in knitr?

Say I have the following code in knitr. How can I run it multiple times with different values of i?
```{r, echo=FALSE}
i<-0.1
```
### X,Y plot of Y=X+e where e is a standard normal distro: mean=0, sd=`r i`
```{r, echo=FALSE}
r<-rnorm(100,mean=0,sd=i)
x<-seq(0,1,length.out=100)
y<-x+r
plot(x,y)
```
EDIT:
As has been suggested ... I tried to do something like this: start a loop in an R code block, have a template in between and then close the loop -- R throws and error.
```{r, echo=FALSE}
for (i in 1:4) {
```
# bla
```{r, echo=FALSE}
}
```
What makes this question tricky is that not only the chunk content (the plot) must be repeated, but the heading as well. That's why we can neither simply reuse the chunk nor just loop over the plot command like
for (i in 1:3) { plot(rnorm(100, sd = i)) }
But it's almost that simple: We loop over the code that produces the plot and output the heading from inside the loop. This requires the chunk option results="asis" and cat to get verbatim markdown output:
```{r, echo=FALSE, results = "asis"}
sdVec <- c(0.1, 0.2, 0.3)
for (sd in sdVec) {
cat(sprintf("\n### X,Y plot of Y=X+e where e ~ N(0, %s)", sd))
r<-rnorm(100,mean=0,sd=sd)
x<-seq(0,1,length.out=100)
y<-x+r
plot(x,y)
}
```
See this answer for related issues.

why does kable not print when used within a function in rmarkdown

I have to repeat certain outputs in many rmarkdown reports and want to write a function to use for this.
Calling a function outputs plots ok when I knit the rmd file but not kable data frames.
For example
---
title: "Markdown example"
output: html_document
---
```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = TRUE)
```
# Markdown example
```{r mtcars}
make_outputs <- function(){
knitr::kable(head(mtcars))
plot(mtcars$mpg, mtcars$cyl)
hist(mtcars$cyl)
}
make_outputs()
```
Displays the plots but not the kable table.
You can do this by using print to print the kable output, setting the results="asis" of the code chunk and then using kable_styling from package kableExtra.
This works for me:
```{r mtcars, results='asis'}
library(kableExtra)
library(knitr)
make_outputs <- function(){
print(kable_styling(kable(head(mtcars))))
plot(mtcars$mpg, mtcars$cyl)
hist(mtcars$cyl)
}
make_outputs()
```
Using a return statement with all objects in a list can help here, You can try recordPlot or plot from base R to solve your problem, By putting each of these plots in list, I managed to get the plots along with your table. Changed your code a bit in return statement to plot each of the plots along with tables like this.
Option1:
Using list in return with all the objects binded together without using lapply in function call
---
title: "Markdown example"
output: html_document
---
```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = TRUE)
```
# Markdown example
```{r mtcars}
make_outputs <- function(){
return(list(hist(mtcars$cyl),
knitr::kable(head(mtcars)),
plot(mtcars$mpg, mtcars$cyl)))
}
make_outputs()
```
Another version (In case you don't want the code to print hist output to your html then you can use below function to suppress it.
make_outputs <- function(){
h1 <- plot(hist(mtcars$cyl, plot=FALSE))
h2 <- knitr::kable(head(mtcars))
h3 <- plot(mtcars$mpg, mtcars$cyl)
return(list(h1, h2, h3))
}
Option2:
Another (better version by using invisible function on lapply to suppress NULL printing, then using results='asis' option in the markdown settings as below gives a clean output than earlier.
---
title: "Markdown example"
output: html_document
---
knitr::opts_chunk$set(echo = FALSE)
knitr::opts_knit$set(root.dir= normalizePath('..'))
knitr::opts_chunk$set(error = FALSE)
```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = TRUE)
```
# Markdown example
```{r mtcars, results='asis'}
make_outputs <- function(){
return(list(plot(hist(mtcars$cyl, plot =FALSE)),
knitr::kable(head(mtcars)),
plot(mtcars$mpg, mtcars$cyl)))
}
invisible(lapply(make_outputs(), print))
```
This has given me a histogram, a scatter plot and a table in the knitted html document. Hope this helps, Not sure though if you wanted this way. Please let me know in case you wanted in any other way.
The problem seems to be related to knitr::kable incorrectly detecting the environment for the printing when it is embedded inside a function. This interferes with its ability to correctly figure out how to format. We can hack around this by placing the object to print in the top level environment before we print it.
---
title: "Markdown example"
output: html_document
---
```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = TRUE)
print_kable = function(x) {
print(kable_print_output <<- x)
cat('\n')
}
```
# Markdown example
```{r mtcars, results='asis'}
make_outputs <- function() {
print_kable(knitr::kable(head(mtcars)))
plot(mtcars$mpg, mtcars$cyl)
print_kable(knitr::kable(tail(mtcars)))
}
make_outputs()
```
I got something similar working by
moving the knitr::kable(head(mtcars)) inside a return() at the end of the function.
including results = 'asis'
e.g.
---
title: "Markdown example"
output: html_document
---
```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = TRUE)
```
# Markdown example
```{r results = 'asis'}
make_outputs <- function(){
print(plot(mtcars$mpg, mtcars$cyl))
print(hist(mtcars$cyl))
return(knitr::kable(head(mtcars)))
}
make_outputs()
```
If you use ggplot for plots, you will need to wrap your plot inside print()

Figure captions with multiple plots in one chunk

I label my figures like this.
---
title: "xxx"
output:
pdf_document:
fig_caption: true
---
And then in each chunk
```{r, fig.cap="some caption"}
qplot(1:5)
```
This works quite nicely. However in chunks where I plot multiple figures within a loop I can't specify a caption. This produces no caption at all:
```{r, fig.cap="another caption"}
qplot(1:5)
qplot(6:10)
```
How can I specify a figure that counts from the same number as the first chunk for each plot?
You can use a fig.cap argument of length 2 (or the size of your loop):
```{r, fig.cap=c("another caption", "and yet an other")}
qplot(1:5)
qplot(6:10)
```
Found an easy way to dynamically produce plots and add them to the pdf with individual captions, using knitr::fig_chunk as described here. This is also a workaround for OPs comment that message=false (or echo=False or results='asis' for that matter) supresses the fig.cap argument.
```{r my-plots, dev='png', fig.show='hide', echo=FALSE}
# generate plots first
qplot(1:5)
qplot(6:10)
```
```{r, echo=FALSE, results='asis'}
# then put them in the document with the captions
cat(paste0("![some caption](", fig_chunk(label = "my-plots", ext = "png", number = 1), ")\n\n"))
cat(paste0("![another caption](", fig_chunk(label = "my-plots", ext = "png", number = 2), ")\n\n"))
```
Hopefully this helps someone who stumbles upon this question in the future.

Resources