26

When using R markdown if one wants to add text using code there are some simple ways to do it.

This is also true for tables, using the kable command is very easy.

However, imagine you want to programmatically insert headers or lists to your report.

```{r, results='asis'}
headers=list("We","are","your","friends")
for (i in list_a){
    #add i as header
}
```

and you want this to be the same as writing in your Rmd file:

#We
#are
#your
#friends

Another example would be to automatically create headers instead of lists:

```{r, results='asis'}
list_a=list("We","are","your","friends")
for (i in list_a){
    #print i to a rmd list
}
```

as before this should have the same result as writing:

*We
*are
*your
*friends

This is not only a formatting problem as the table of context for Rmd files is created dynamically according to these headers.

ManuelLevi
  • 358
  • 1
  • 4
  • 9

4 Answers4

27

You need to construct your wanted markdown in R and use that together with the argument results = 'asis' in your chunk options. Hence, something like the following will do what you want:

```{r, results='asis'}
headers <- list("We","are","your","friends")
for (i in headers){
  cat("#", i, "\n")
}
```

The for-loop here will create the output

# We 
# are 
# your 
# friends 

which is used directly as input in the .md document.

Anders Ellern Bilgrau
  • 9,928
  • 1
  • 30
  • 37
  • 3
    Should there be any specific problem about using this after a plot? If I do something like: `for (i in 1:2){ cat("#",names(data)[i],"\n"); nona_data = data[i][is.na(data[i])==F]; vioplot(nona_data, col="gold"); hist(nona_data,xlab="Small Particles", main=names(data)[i]) ;}` The first header works, but not the second. – ManuelLevi Oct 27 '14 at 14:19
  • Yes, that may be a problem and may not work. The `results == 'asis'` is usually for text-output and is probably not compatible with the output of when plotting. However, I'm not quite sure. Anyway, it should be easy to split the chunk up into two (one for the plots and one for the text). – Anders Ellern Bilgrau Oct 27 '14 at 14:25
  • 5
    The order is important in this task as a new header is needed for each plot, how would you split the chunk? – ManuelLevi Oct 27 '14 at 15:08
8

Use the pander package, which transform R objects into Pandoc's markdown:

> headers=list("We","are","your","friends")
> list_a=list("We","are","your","friends")
> library(pander)
> pandoc.header(headers)

# We

# are

# your

# friends
> pander(list_a)


  * We
  * are
  * your
  * friends

<!-- end of list -->

The first example used a helper function to create the headers, while the second demo simply called the generic S3 method, that can robustly transform a variety of R objects into markdown.

daroczig
  • 28,004
  • 7
  • 90
  • 124
  • 1
    I use this for loops where each iteration generates a loop, then a plot. I found that I had to include a `cat("\n")` statement after printing my plot or any headers after the first iteration were rendered as text instead of markdown. – DonJ Nov 17 '17 at 15:11
1

For people who want plots below each header, this is how I do it.

```{r, results="asis"}

for (i in headers){
      cat("# ", i, "\n",
          knitr::knit_child("plot.Rmd", quiet = TRUE), "\n")
    }

```

In the plot.Rmd put your plot code in it, e.g.

```{r}
# plotting code
```
moho wu
  • 471
  • 4
  • 13
0

This solution worked for me, compiling .Rmd to PDF in R 3.6.3:

```{r plot_loop_chunk, results='asis', tidy=FALSE}

for(i in 1:10){
    cat("#", "Header", i, "\n")

    print(<some loop-dependent plot>)

    cat("\n")
    cat("\n")
}

```
Brian D
  • 2,570
  • 1
  • 24
  • 43