how to use a for loop in rmarkdown? - r

Consider this simple example:
---
title: "Untitled"
output: ioslides_presentation
---
```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = FALSE)
```
## Slide with R Output
```{r t, warning=FALSE, message=FALSE}
library(knitr)
library(kableExtra)
library(dplyr)
for(threshold in c(20, 25)) {
cars %>%
filter(dist < threshold) %>%
kable('html') %>%
kable_styling(bootstrap_options = "striped")
}
```
Here I simply want to print each output of the for loop into a different slide. In this example, there are two calls to kablethat should go on two different slides.
The code above does not work. Am I even using the right packages for that? Any ideas?
Thanks!

You can use the asis option:
---
title: "Untitled"
output: ioslides_presentation
---
```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = FALSE)
library(knitr)
library(kableExtra)
library(dplyr)
# needed so r will include javascript/css dependencies needed for striped tables:
kable(cars, "html") %>% kable_styling(bootstrap_options = "striped")
```
```{r, results = "asis"}
for (threshold in c(20, 25)) {
cat("\n\n##\n\n")
x <- cars %>%
filter(dist < threshold) %>%
kable('html') %>%
kable_styling(bootstrap_options = "striped")
cat(x)
}
```

To get rid of that bogus table, you can try to put options(kableExtra.html.bsTable = T) in your setup section.

Here's the start of a solution. You can print strings with markdown, either by making the strings yourself or using pander's pandoc.* functions. If you set results="asis" for that chunk, it will get compiled the same as any other markdown. I used cat to make the ## headings, but commented out two pander functions that you could try also to make headers or horizontal rules to split slides.
There's more detail on the pander functions here, plus other SO questions such as this one.
---
title: "Untitled"
output: ioslides_presentation
---
```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = FALSE)
library(knitr)
library(kableExtra)
library(dplyr)
```
```{r, results='asis'}
for(threshold in c(20, 25)) {
# pander::pandoc.header(sprintf("Threshold = %s", threshold))
# pander::pandoc.horizontal.rule()
cat(paste("\n##", "Threshold =", threshold), "\n")
tbl <- cars %>%
filter(dist < threshold) %>%
kable(format = "html") %>%
kable_styling(bootstrap_options = "striped")
print(tbl)
}
```
One issue is that when I knit this, I'm not getting the striped table that you'd expect. If I add a slide before this chunk and put a table in it with these kableExtra settings, I do get stripes, but the first table is also pretty ugly...I'm not sure if that's a bug or conflicting CSS somewhere or what.

Related

Reused code-chunks in Rmarkdown not working with magrittr pipe

The following is based on content within The R Markdown Cookbook which suggests that named code chunks can be re-used.
The following minimal (albeit contrived) example works as expected:
---
output: html_document
---
```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = TRUE)
library (magrittr)
```
```{r filterCyl, include=FALSE, eval=FALSE}
dplyr::filter(cyl == 6L)
```
```{r filterGear, include=FALSE, eval=FALSE}
dplyr::filter(gear == 4L)
```
```{r, eval=FALSE}
mtcars %>%
<<filterCyl>>
```
However, replacing the lower-most block with:
```{r, eval=FALSE}
mtcars %>%
<<filterCyl>> %>%
<<filterGear>>
```
...results in the following being shown in the resulting HTML:
mtcars %>%
<<filterCyl>> %>%
dplyr::filter(gear == 4L)
The <<filterCyl>> block is not being substituted in as I'd expect.
If I remove the %>% operators from that final block, it does get subsituted in; however, the resulting R code isn't valid.
Does this appear to be a bug? Is there some workaround that could be used here?

Rmarkdown to docx less-than symbol in table caption

I would like to use the < symbol in a table caption of a Rmarkdown that converts to a docx document. I am using the flextable package as this gives a lot of (needed) flexibility to tables in the docx format.
But I am really confused by the multiple conversion steps through pandoc. It does not seem so easy to get to the < as it is a special coding HTML character. I have read that in HTML you would escape it via <. This gives me the problem that the & has to be escaped, too. The conversion then turns < into &lt; (as it converts the & into &) and \\< would yield me &amp;lt; (as it converts the & of the & again). Latex does not seem to work either, I've tried <, $<$ and $\\textless$ but to no avail.
All combinations basically follow the same logic, i.e. that < are correctly transformed to < but then the HTML is not converted again.
Any idea how to solve this? What do I miss?
Example RMD file:
---
title: "Untitled"
author: "Unkown"
date: "1/25/2021"
output: bookdown::word_document2
---
```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = TRUE)
library(flextable)
library(tidyverse)
```
## R Markdown
This is an R Markdown document, see Table \#ref(tab:test).
```{r test, echo = F}
flextable(head(cars, n = 10)) %>%
bold(part = "header") %>%
autofit() %>%
set_caption("Table: (\\#tab:test) Example caption with less-than symbol: \\< or < or < or $<$ or $\\textless$")
```
This should answer the question about < and > in the captions
---
title: "Untitled"
output: bookdown::word_document2
---
```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = TRUE)
library(flextable)
library(tidyverse)
```
## R Markdown
This is an R Markdown document, see Table \#ref(tab:test).
```{r test, echo = F, tab.id="test"}
flextable(head(cars, n = 10)) %>%
bold(part = "header") %>%
autofit() %>%
set_caption("Example caption with less-than symbol: > and <")
```
You could use the package officedown. It will make the references as real Word references, it also offers few features to customize your captions:
---
output:
bookdown::markdown_document2:
base_format: officedown::rdocx_document
---
```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = FALSE, tab.cap.style="Table Caption")
library(flextable)
library(tidyverse)
```
```{r test1}
flextable(head(cars, n = 10)) %>%
bold(part = "header") %>%
autofit() %>%
set_caption("Example caption with less-than symbol: > and <")
```
```{r "test2", tab.cap="Example caption with less-than symbol: > & <"}
flextable(head(cars, n = 10)) %>%
bold(part = "header") %>%
autofit()
```
\newpage
See \#ref(tab:test1).
See \#ref(tab:test2).

Printing any number of dataframes stored in list as paged tables in rmarkdown

I often want to print out the dataframes contained in a list as paged tables in my rmarkdown documents. Calling each dataframe individually renders the desired ouptut if the right df_print option is selected. However, the point of having a list is that the number of dataframes varies depending on the parameters passed to the rmarkdown document; so that's no real solution.
Based on Vincent Guyader's answer to this question and on this example of rmarkdown::paged_table, I've tried to do the following without success.
Is there a way to achieve this at all? I'd be happy to use any package that supports pagination remotely resembling the df_print option.
---
title: "Printing paged tables from a list of dataframes in Rmarkdown"
output:
html_document:
df_print: paged
---
```{r}
library(DT)
library(rmarkdown)
library(purrr)
library(knitr)
df_list <- list("cars" = mtcars, "flowers" = iris)
knitr::opts_chunk$set(echo = FALSE, warning = FALSE, message = FALSE, results='asis')
```
### Desired output but impossible to generalise
```{r}
df_list[["cars"]]
```
```{r}
df_list[["flowers"]]
```
### datatable shows as blanks on the page
```{r}
map(df_list, ~DT::datatable(.x) %>%
htmltools::tagList() %>%
print())
```
### rmarkdown outputs dataframe contents as one very long string
```{r}
map(df_list, rmarkdown::paged_table)
```
The issue is that the JS dependencies needed to render the Datatable are not included in the HTML output. A workaround which I borrowed from here is to add a code chunk
```{r init-step, include=FALSE}
DT::datatable(mtcars)
```
outside of the loop or map statement which ensures that the JS dependencies are included. Also, I would recommend to switch to purrr::walk as using map has the effect that the tables are plotted twice.
---
title: "Printing paged tables from a list of dataframes in Rmarkdown"
output:
html_document:
df_print: paged
---
```{r}
library(DT)
library(rmarkdown)
library(purrr)
library(knitr)
df_list <- list("cars" = mtcars, "flowers" = iris)
knitr::opts_chunk$set(echo = FALSE, warning = FALSE, message = FALSE, results='asis')
```
### Desired output but impossible to generalise
```{r}
df_list[["cars"]]
```
```{r}
df_list[["flowers"]]
```
### datatable shows as blanks on the page
```{r init-step, include=FALSE}
DT::datatable(mtcars)
```
```{r}
walk(df_list, ~DT::datatable(.x) %>%
htmltools::tagList() %>%
print())
```
When using results='asis' argument, the renderer (here DT) has to be initialized once before being applied on a asis list.
This seems to be a general problem, see here with leaflet, and here with Highcharter.
The answer to this general question has been given here.
In this case:
---
title: "Printing paged tables from a list of dataframes in Rmarkdown"
output:
html_document:
df_print: paged
---
```{r,}
library(DT)
library(rmarkdown)
library(purrr)
library(knitr)
df_list <- list("cars" = mtcars, "flowers" = iris)
knitr::opts_chunk$set(echo = FALSE, warning = FALSE, message = FALSE, results='asis')
# initialize the renderer
data.frame() %>%
DT::datatable() %>%
knitr::knit_print() %>%
attr('knit_meta') %>%
knitr::knit_meta_add() %>%
invisible()
```
```{r , results='asis'}
#Remove already printed element and print the rest
df_list[[1]] <- NULL
map(df_list, ~DT::datatable(.x) %>%
htmltools::tagList() %>%
print())
```

how can I show my "ztable" when I use "knit to HTML" in R?

I am having a problem with my ztable,
I want to knit my Rmarkdown file to HTML but I cannot find a way to display the table I created with ztable:
z=ztable(loucaste) %>% makeHeatmap(palette = "Blues") %>% print(caption="Table 2.)
I tried to set
options(ztable.table="html")
and put this at the beginning as I read somewhere else
output: html_document
header-includes: \usepackage{colortbl}
but it doesn't work when I knit to HTML. My intention was to create a sort of formatting table similar to the ones made on excel and ztable looks like the only way.
Try this minimal Rmd. The key seems to be options(ztable.type = "html") and in the chunk that generates the table, r results='asis'
If that works for you, substitute your code in the appropriate place i.e. ztable(loucaste) %>% makeHeatmap(palette = "Blues") %>% print(caption="Table 2.).
---
title: "ztable"
output: html_document
---
```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = TRUE)
library(ztable)
library(magrittr)
options(ztable.type = "html")
```
## R Markdown
```{r results='asis'}
matrix(1:100, nrow = 10) %>%
as.data.frame() %>%
ztable() %>%
makeHeatmap() %>%
print(caption = "table 2")
```

Using R-markdown knitr hooks to custom format tables in HTML reports

I am trying to set up a knitr::knit_hooks() to automatically format data frame output of an R-markdown chunk with kableExtra in my HTML report.
I would like to not repeatedly add the following lines (or any lines) to the end of each chunk of tabulated data:
head(iris) %>%
kable("html") %>%
kable_styling("hover", full_width = FALSE)
I came up with one solution based on this answer that works by evaluating the chunk source (see my answer below that includes some issues that I have with this approach); I'm hoping there might be a better solution using the chunk output.
Here is an example .Rmd with an outline of what I would like to achieve.
---
title: "Untitled"
author: "Paul"
date: "25 September 2018"
output: html_document
---
```{r setup, include = F}
library(dplyr)
library(kableExtra)
library(knitr)
data(iris)
default_source_hook <- knit_hooks$get('source')
knit_hooks$set(
output = function(x, options) {
x %>%
kable("html") %>%
kable_styling("hover", full_width = FALSE)
},
source = function(x, options) {
if(is.null(options$table))
default_source_hook(x, options)
else {
eval(parse(text = x)) %>%
kable("html") %>%
kable_styling("hover", full_width = F)
}}
)
```
Desired chunk input:
```{r test, echo = F}
head(iris)
```
Desired output will look like:
```{r output, echo = F}
head(iris) %>%
kable("html") %>%
kable_styling("hover", full_width = FALSE)
```
Solution using the source chunk output:
```{r table_format, results = "hide", table = T, eval = F}
head(iris)
```
Thank you.
If using knit hooks is not necessary, the following might help. The idea is to just define a function that prints whatever it gets exactly the way you want. This does not eliminate all typing, but reduces it substantially.
---
title: "Untitled"
author: "Paul"
date: "25 September 2018"
output: html_document
---
```{r setup, include = F}
library(dplyr)
library(kableExtra)
library(knitr)
tbl_out <- function(data) {
data %>% kable("html") %>% kable_styling("hover", full_width = FALSE)
}
```
Prints as desired:
```{r test, echo = F}
head(iris) %>% tbl_out()
```
Output:
I found a work-around by using the knit_hooks() source as the formatted chunk output.
The difficulty in formatting the chunk output is that character data is passed to the hook. Drawing inspiration from the linked answer in the OP, I found a solution by evaluating the chunk source in knit_hooks().
This solution re-evaluates the chunk and is piped into the desired KableExtra formatting.
I needed to add a new chunk option table = T so that the formatting was only applied to source code that produces a data table; results = "hide" was also needed so the default chunk output was not included in the report.
---
title: "Untitled"
author: "Paul"
date: "27 September 2018"
output: html_document
---
```{r setup, include = F}
library(dplyr)
library(ggplot2)
library(kableExtra)
library(knitr)
default_source_hook <- knit_hooks$get('source')
knit_hooks$set(
source = function(x, options) {
if(is.null(options$table))
default_source_hook(x, options)
else {
eval(parse(text = x)) %>%
kable("html") %>%
kable_styling("hover", full_width = F)
}
}
)
data(iris)
```
## Normal
With no chunk options:
```{r normal}
head(iris)
```
## The desired ouptut
With chunk options `results = "hide"` and `table = T`:
```{r table_format, results = "hide", table = T, eval = F}
head(iris)
```
## It still work as normal for other other output types
With no chunk options:
```{r image}
iris %>%
ggplot(aes(x = Sepal.Length, y = Sepal.Width, group = Species)) +
geom_point()
```
There are a few problems with this solution
the code used to produce the table is now unavailable
eval = F should be included - especially if the code will take a while to run (as it is again evaluated in the hook)
I'm replacing 2 lines of code with 3 chunk options - although not a deal killer it's not quite as automagical as I would have liked.

Resources