{r setup, include=FALSE, message=FALSE, results="hide"}
knitr::opts_chunk$set(echo = TRUE)
library(knitr)
library(kfigr)
library(dplyr)
library(png)
library(grid)
library(pander)
library(ggplot2)
Question
Loops in rmarkdown: in-text figure reference? figure captions?
Goal
Use a for loop to create sections with text, in-text results, and multiple figure references with associated figure captions in the figure list. The figure references/numbering should be seemless with figures numbered before and after these new sections.
Note: The figures referenced in the for loop are generated earlier in the text, saved as pngs, and then re-loaded. This might seem clunky for the purpose of this example, but the actual figs are maps and are slow to generate (I plan to comment out the loop that generates the figures once I have them how I want).
{r echo = FALSE, warnings=FALSE, message=FALSE, results="hide"}
Data: Each year we have a different number of strata, hence the need for a loop.
df <- rbind(
data.frame(strata = rep("A", 10), x = rnorm(10, mean= 10), y = rnorm(10, mean = 15),z = rnorm(10, mean = 20)),
data.frame(strata = rep("B", 10), x = rnorm(10, mean= 5), y = rnorm(10, mean = 10), z = rnorm(10, mean = 15)),
data.frame(strata = rep("C", 10), x = rnorm(10, mean= 15), y = rnorm(10, mean = 20), z = rnorm(10, mean = 10)))
first_plot: the figure that should appear in the list before for loop creates the sections by strata
first_plot <- ggplot(df, aes(x, fill=strata)) + geom_histogram()
last_plot: the figure that should appear in the list after the for loop creates the sections by strata
last_plot <- ggplot(df, aes(x = strata, y = z)) + geom_boxplot()
Figure generation (this is the part that will be commented out later in my version once I have the maps how I want)
strat <- unique(df$strata)
for (i in seq_along(strat)) {
sub <- df %>% filter(strata %in% strat[i])
fig1 <- ggplot(sub, aes(x = x, y = y)) + geom_point()
ggsave(fig1, file=paste0("fig1_", strat[i], ".png"))
fig2 <- ggplot(sub, aes(x = x, y = z)) + geom_point()
ggsave(fig2, file=paste0("fig2_", strat[i], ".png"))
}
Load the png's
df_figs <- list.files(pattern = "\\.png$")
for (i in df_figs){
name <- gsub("-",".",i)
name <- gsub(".png","",name)
i <- paste(".\\",i,sep="")
assign(name,readPNG(i))
}
Introduction section
Some introductory text in the report and a figure r figr('first_plot',TRUE, type='Figure')
.
```{r echo = FALSE, warnings=FALSE, message=FALSE, results = "asis"}
# Summary of results and image file names that will be references in text
results <- df %>%
group_by(strata) %>%
dplyr::summarise_each(funs(mean)) %>%
mutate(fig1 = paste0("fig1_", strata),
fig2 = paste0("fig2_", strata))
#Text template (each strata will have its own section)
template <- "# The %s stratum
The mean of *x* in %s stratum was %1.1f. Relationships between *x* and *y* and *x* and *z* can be found in `r figr('%s', TRUE, type='Figure')` and `r figr('%s', TRUE, type='Figure')`.
"
#Create markdown sections in for loop
for(i in seq(nrow(results))) {
current <- results[i, ]
cat(sprintf(template,
current$strata, current$strata,
current$x,
current$fig1, current$fig2))
}
#Also doesn't work:
template <- "# The %s stratum
The mean in %s stratum was %1.0f. Results can be found in "
template2 <- " and "
template3 <- ".
"
`figr('%s', TRUE, type='Figure')` and `figr('%s', TRUE, type='Figure')`."
#For loop
for(i in seq(nrow(results))) {
current <- results[i, ]
cat(sprintf(template,
current$strata, current$strata,
current$mean,
current$fig_1, current$fig_2))
print(paste0("`r figr(",paste0("'", current$fig1,"'"), TRUE, type='Figure'))
cat(sprintf(template2))
print(paste0("`r figr(",paste0("'", current$fig2,"'"), "TRUE, type='Figure'),`"))
cat(sprintf(template3))
}
```
Conclusion section
Some discussion text in the report and figure r figr('last_plot',TRUE, type='Figure')
.
Figures
*NOTE:* I don't know how to automate the looped portion of the list of figures here, so I've done it by hand.
```{r 'first_plot', echo=FALSE, warning=FALSE, fig.width=6.5, fig.height=6, fig.cap="The caption for the first figure."}
suppressMessages(print(first_plot))
```
```{r 'fig1_A', echo=FALSE, warning=FALSE, fig.width=6.5, fig.height=6, fig.cap="Caption text for fig1_A."}
grid.raster(fig1_A)
```
```{r 'fig2_A', echo=FALSE, warning=FALSE, fig.width=6.5, fig.height=6, fig.cap="Caption text for fig2_A."}
grid.raster(fig2_A)
```
```{r 'fig1_B', echo=FALSE, warning=FALSE, fig.width=6.5, fig.height=6, fig.cap="Caption text for fig1_B."}
grid.raster(fig1_B)
```
```{r 'fig2_B', echo=FALSE, warning=FALSE, fig.width=6.5, fig.height=6, fig.cap="Caption text for fig2_B."}
grid.raster(fig2_B)
```
```{r 'fig1_C', echo=FALSE, warning=FALSE, fig.width=6.5, fig.height=6, fig.cap="Caption text for fig1_C."}
grid.raster(fig1_C)
```
```{r 'fig2_C', echo=FALSE, warning=FALSE, fig.width=6.5, fig.height=6, fig.cap="Caption text for fig2_C."}
grid.raster(fig2_C)
```
```{r 'last_plot', echo=FALSE, warning=FALSE, fig.width=6.5, fig.height=6, fig.cap="The caption for the last figure."}
suppressMessages(print(last_plot))
```
SOLUTIONS
knit_expand()
captioner
instead ofkfigr
brew
I will give you all the SO points.Libraries
library(knitr) library(dplyr) library(png) library(grid) library(pander) library(ggplot2) library(devtools) library(captioner)
Create a
fig_nums()
function using thecaptioner
package (https://github.com/adletaw/captioner/blob/master/vignettes/using_captioner.Rmd)Data
Each year we have a different number of strata, hence the need for a loop.
first_plot: the figure that should appear in the list before for loop creates the sections by strata
last_plot: the figure that should appear in the list after the for loop creates the sections by strata
Figure generation
Comment this section out once you have figs how you want. This step will not feel convoluted, unnatural, suboptimal, unnecessary, or like a very bad idea if you do a lot of mapping in R.
Load the png's
Introduction
Some introductory text in the report and a figure
r fig_nums("first_plot", display="cite")
.Results and image file names that will be referenced in text:
Creates section for each strata
Conclusion
Some discussion text in the report and figure
r fig_nums("last_plot",display="cite")
.List of Figures