Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

multiple (R) plotly figures generated in a Rmarkdown (knitr chunk) document

I try to create multiple plotly figures in a Rmarkdown document using loop or lapply.

The R script:

require(plotly)
data(iris)
b <- lapply(setdiff(names(iris), c("Sepal.Length","Species")),
            function(x) {
              plot_ly(iris, 
                      x = iris[["Sepal.Length"]],
                      y = iris[[x]], 
                      mode = "markers")
            })
print(b)

works well, but it fails when included in a knitr chunk:

---
output: html_document
---

```{r,results='asis'}
require(plotly)
data(iris)
b <- lapply(setdiff(names(iris), c("Sepal.Length","Species")),
            function(x) {
              plot_ly(iris, 
                      x = iris[["Sepal.Length"]],
                      y = iris[[x]], 
                      mode = "markers")
            })
print(b)
```

I tried replacing print(b) with a combination of lapply eval and parse but only the last figure was displayed.

I suspect a scoping/environment issue but I cannot find any solution.

like image 225
frdbd Avatar asked Feb 04 '16 06:02

frdbd


3 Answers

Instead of print(b), put b in htmltools::tagList(), e.g.

```{r}
library(plotly)

b <- lapply(
  setdiff(names(iris),
          c("Sepal.Length","Species")),
  function(x) {
    plot_ly(iris, 
            x = iris[["Sepal.Length"]],
            y = iris[[x]], 
            mode = "markers")
  }
)

htmltools::tagList(b)
```

Note: Before Plotly v4 it was necessary to convert the Plotly objects to htmlwidgets using Plotly's as.widget() function. As of Plotly v4 they are htmlwiget objects by default.

For people who are interested in the technical background, you may see this blog post of mine. In short, only top-level expressions get printed.

like image 172
Yihui Xie Avatar answered Nov 16 '22 02:11

Yihui Xie


I found a "dirty" solution by using temp file and kniting it :

```{r,echo=FALSE}
mytempfile<-tempfile()
write("```{r graphlist,echo=FALSE}\n",file=mytempfile)
write(paste("p[[",1:length(p),"]]"),file=mytempfile,append = TRUE)
write("\n```",file=mytempfile,append = TRUE)
```

`r knit_child(mytempfile, quiet=T)`

But it's unsatisfactory.

like image 33
frdbd Avatar answered Nov 16 '22 02:11

frdbd


For anyone struggling with a loop, here's what worked for me.

p=list()
for (n in 1:3){
  p[[n]] <- plot_ly(x = 1:100, y = rnorm(100)+n, mode = 'lines', type="scatter")
}
htmltools::tagList(p)

I.e. it doesn't matter if the list p is created in a loop or lapply, etc. as long as you call htmltools::tagList outside the loop.

Thanks to Yihui for helping me get there and for immense work developing and helping with these tools.

like image 37
glacierbliss Avatar answered Nov 16 '22 01:11

glacierbliss