8

Is that possible to use ggplotly() or datatable() in RMarkdown from inside a for loop or function? Example:

---
title: "Using `ggplotly` and `DT` from a `for` loop in Rmarkdown"
output: html_document
---

```{r setup, include=FALSE}
library(ggplot2); library(DT)
```

## Without `for` loop - works

```{r}
datatable(cars)

g <- ggplot(cars) + geom_histogram(aes_string(x=names(cars)[1] ))
ggplotly(g) 
```

## From inside the `for` loop  - does not work (nothing is printed)

```{r}
for( col in 1:ncol(cars)) {

  datatable(cars)          # <-- does not work 
  print( datatable(cars) ) # <-- does not work either

  g <- ggplot(cars) + geom_histogram(aes_string(x=names(cars)[col] ) )

  ggplotly (g)            # <-- does not work 
  print ( ggplotly (g) )  # <-- does not work either
}
```

I wonder if this is because interactive outputs cannot be print-ed at all - by design.
No such problem existing when printing non-interactive outputs.

PS This is related to: Automating the generation of preformated text in Rmarkdown using R
Looping headers/sections in rmarkdown?

IVIM
  • 2,167
  • 1
  • 15
  • 41
  • 1
    Have you seen this: https://stackoverflow.com/questions/36234169/plotly-charts-in-a-for-loop – J_F Mar 14 '20 at 18:17
  • Thanks for the link - I looked int it. It does offer a solution, but only if you just want to loop ggplotly (for that you'll need to stop using ggplot2 and use plotly directly). However, I'm trying to have a combination of text,graphs,tables- all generated automatically after printing each Section header. – IVIM Mar 15 '20 at 02:05
  • 1
    You can still use ggplotly. See https://stackoverflow.com/questions/61906480/how-to-display-ggplotly-plots-with-dynamically-created-tabs-and-for-loops/61909785#61909785. Also it is possible to combine different htmlwidgets – stefan Jun 24 '20 at 10:36
  • Found this related link ( `ggplotly` from inside `for` loop in `.Rmd` file does not work). https://github.com/ropensci/plotly/issues/570 - Seems like it is still not resolved :( – IVIM Jun 26 '20 at 16:25

2 Answers2

17

This is the solution from the post I added in my comment adapted to your case:

---
title: "Using `ggplotly` and `DT` from a `for` loop in Rmarkdown"
output: html_document
---

```{r setup, include=FALSE}
library(plotly); library(DT)
```

```{r, include=FALSE}
# Init Step to make sure that the dependencies are loaded
htmltools::tagList(datatable(cars))
htmltools::tagList(ggplotly(ggplot()))
```

```{r, results='asis'}
for( col in 1:ncol(cars)) {
  
  print(htmltools::tagList(datatable(cars)))
  
  g <- ggplot(cars) + geom_histogram(aes_string(x=names(cars)[col] ) )

  print(htmltools::tagList(ggplotly(g)))

}
```
stefan
  • 90,330
  • 6
  • 25
  • 51
  • 1
    this is great. However I don't get why the cars need to be initiated. I tried it on my pc and without the init step it just fails. The reason why I'm asking is because I have a complicated list of tables that use the for loop through and I can't seem to initiate with a for loop! – Ahdee Jul 07 '20 at 01:45
  • scratch above comment: to get list to work just simply initiate with lappy, like this, ```l = list ( c=cars, c2=iris ) htmltools::tagList( lapply(l, datatable) )``` – Ahdee Jul 07 '20 at 04:03
  • 2
    Hi @Ahdee. We don't need to init cars. The init step makes sure that the javascript dependencies, i.e. plotly.js and DataTables.js, are included in the html document. – stefan Jul 07 '20 at 09:59
  • Or if using `%>%` notation... ```for(col in 1:ncol(cars)) { cars %>% select(all_of(col)) %>% DT::datatable(options = list(paging=F)) %>% print(htmltools::tagList(.)) } ``` – Brian D Mar 17 '22 at 18:59
0

This seems to be a persistent problem with RMarkdown. Here is the work around however, found here:

lotlist = list()

for (VAR in factor_vars) {
    p <- ggplot(mtcars, aes_string(x = "mpg", y = "wt", color = VAR)) + geom_point()
    plotlist[[VAR]] = ggplotly(p)
}
htmltools::tagList(setNames(plotlist, NULL))
IVIM
  • 2,167
  • 1
  • 15
  • 41