Loops in Rmarkdown: How to make an in-text figure reference? Figure captions?
<p><code>{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)
</code></p>

<h2>Question</h2>

<p>Loops in rmarkdown: in-text figure reference? figure captions?</p>

<h2>Goal</h2>

<p>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. </p>

<p><em>Note:</em> 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).</p>

<pre><code>{r echo = FALSE, warnings=FALSE, message=FALSE, results="hide"}
</code></pre>

<h3>Data: Each year we have a different number of strata, hence the need for a loop.</h3>

<pre><code>df &lt;- 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)))
</code></pre>

<h3>first_plot: the figure that should appear in the list before for loop creates the sections by strata</h3>

<pre><code>first_plot &lt;- ggplot(df, aes(x, fill=strata)) + geom_histogram()
</code></pre>

<h3>last_plot: the figure that should appear in the list after the for loop creates the sections by strata</h3>

<pre><code>last_plot &lt;- ggplot(df, aes(x = strata, y = z)) + geom_boxplot()
</code></pre>

<h3>Figure generation (this is the part that will be commented out later in my version once I have the maps how I want)</h3>

<pre><code>strat &lt;- unique(df$strata)

for (i in seq_along(strat)) {
  sub &lt;- df %&gt;% filter(strata %in% strat[i])
  fig1 &lt;- ggplot(sub, aes(x = x, y = y)) + geom_point()
  ggsave(fig1, file=paste0("fig1_", strat[i], ".png"))
  fig2 &lt;- ggplot(sub, aes(x = x, y = z)) + geom_point() 
  ggsave(fig2, file=paste0("fig2_", strat[i], ".png"))
}    
</code></pre>

<h3>Load the png's</h3>

<pre><code>df_figs &lt;- list.files(pattern = "\\.png$")
for (i in df_figs){  
   name &lt;- gsub("-",".",i)
   name &lt;- gsub(".png","",name)  
   i &lt;- paste(".\\",i,sep="")
   assign(name,readPNG(i))
}
</code></pre>

<h2>Introduction section</h2>

<p>Some introductory text in the report and a figure <code>r figr('first_plot',TRUE, type='Figure')</code>.</p>

<pre><code>```{r echo = FALSE, warnings=FALSE, message=FALSE, results = "asis"}

# Summary of results and image file names that will be references in text
results &lt;- df %&gt;% 
  group_by(strata) %&gt;% 
  dplyr::summarise_each(funs(mean)) %&gt;% 
  mutate(fig1 = paste0("fig1_", strata),
         fig2 = paste0("fig2_", strata))

#Text template (each strata will have its own section)
template &lt;- "# 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 &lt;- results[i, ]
  cat(sprintf(template, 
              current$strata, current$strata, 
              current$x, 
              current$fig1, current$fig2))
}

#Also doesn't work:
template &lt;- "# The %s stratum
The mean in %s stratum was %1.0f. Results can be found in "
template2 &lt;- " and "
template3 &lt;- ".

"

`figr('%s', TRUE, type='Figure')` and `figr('%s', TRUE, type='Figure')`."

#For loop
for(i in seq(nrow(results))) {
  current &lt;- 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))
 }
```
</code></pre>

<h2>Conclusion section</h2>

<p>Some discussion text in the report and figure <code>r figr('last_plot',TRUE, type='Figure')</code>.</p>

<h2>Figures</h2>

<pre><code>*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))
```
</code></pre>