2

I am using lists to collect a number of QC plots and tables generated by functions that should be included in a final Rmd markdown html document. The code, as far as I can see, works as expected. All plots and tables are generated and collected. And they are also properly printed in the source window when the whole script is executed.

However, when I knit the document, only the plots are included the way I expect, while the datatables are not. I am not sure why and how to fix this.

Below is a toy example. Apologies for the very long post, but I wanted to show the different behaviors.

Output of individual plot and table in the source window:

library(DT)

plot(cars)

datatable(cars)

Output of plots and tables from lists:

library(DT)

qc_tables <- list()
qc_plots <- list()

qc_plots[[length(qc_plots) + 1]] <- plot(cars)
qc_plots[[length(qc_plots) + 1]] <- plot(iris)
for (p in qc_plots) { print(p) }

qc_tables[[length(qc_tables) + 1]] <- datatable(cars)
qc_tables[[length(qc_tables) + 1]] <- datatable(iris)
for (p in qc_tables) { print(p) }

Screenshot of output in source window:

Now knitting and html output:

---
title: "R Notebook"
output:
  html_document
---

# Direct output of plots and Data.Tables

```{r}
library(DT)

plot(cars)
datatable(cars)

plot(iris)
datatable(iris)

```

# Output of plots and Data.Tables from lists

```{r}
library(DT)

qc_tables <- list()
qc_plots <- list()

qc_plots[[length(qc_plots) + 1]] <- plot(cars)
qc_plots[[length(qc_plots) + 1]] <- plot(iris)

for (p in qc_plots) { print(p) }

qc_tables[[length(qc_tables) + 1]] <- datatable(cars)
qc_tables[[length(qc_tables) + 1]] <- datatable(iris)

for (p in qc_tables) { print(p) }
```

Markdown file with direct output:

enter image description here

Markdown output is missing when generating them via a list:

enter image description here

Created on 2021-01-27 by the reprex package (v0.3.0)

Mario Niepel
  • 1,095
  • 4
  • 19

1 Answers1

2

I found help here: https://github.com/rstudio/DT/issues/67

this worked for me, it's not a loop, but generated the desired output.
chunk at the top:

library(knitr)
library(DT)

now there are two options, firstly, if your data is in dataframes and you want to format them all the same way:

dflist <- list(iris,cars)
htmltools::tagList(
  lapply(dflist, datatable)
)

secondly, if, as pointed out in the comments, you format the datatables ahead of time and have them in a list:

qc_tables <- list()
qc_tables[[length(qc_tables) + 1]] <- datatable(cars)
qc_tables[[length(qc_tables) + 1]] <- datatable(iris)
htmltools::tagList(
  lapply(qc_tables, print)
)

results in Rmd: DT results

brian avery
  • 403
  • 2
  • 8
  • Thank Brian. Unfortunately this solution does not work for me. The function that generates these QC tables is rather long and specific: it takes a number of different slices of the data and then formats these tables specific to the data subset. So the challenge is to extract the already generated tables from the list. I can enumerate them one-by-one for now, since the number of tables doesn't vary. However, that solution is not particularly elegant... but it will work for now. – Mario Niepel Jan 27 '21 at 16:08
  • I updated my answer to work with dataframes in the list or DTs in the list. – brian avery Jan 27 '21 at 16:52
  • Sweet! That works. Thank you. Next to try and understand why it doesn't work out of the box and needs the additional wrapping by `htmltools::tagList`... – Mario Niepel Jan 27 '21 at 17:07
  • 1
    not a very sophisticated answer, but I think it is since the output of `datatable` is ultimately an HTML object, so you need `htmltools::tagList` to render them correctly when there are multiples. maybe? – brian avery Jan 27 '21 at 18:47
  • Thanks for taking a stab, Brian. I'm just confused as to why they seem to render just fine when I manually print them (e.g. `print(qc_plot[[1]], qc_plot[[2]], ...`) but not when I'm ostensibly doing the same thing in a `for` loop or via `lapply`. – Mario Niepel Jan 27 '21 at 19:22