2
votes

Within Rstudio, I try to dynamically render plotly plots into an HTML report using knitr render from a .R source file. knitr renders the plotly plots as long as they are not within a lapply loop. But once I try to output them from within a lapply loop they are note rendered. I need to use a loop because I need to programatically build my HTML reports with various numbers of plots with various names.

Here is the command that I execute in the console to create the HTML report from my plotlytest.R source file :

render("plotlytest.R")

and here is my example source file called plotlytest.R :

#'---
#'author: "pokyah"
#'output: 
#'  html_document:
#'    theme: flatly
#'    toc: true
#'    toc_depth: 6
#'    toc_float:
#'      collapsed: false
#'      smooth_scroll: true
#'title: "Plotly test"
#'date: \`r format(Sys.Date(), " %d-%m-%Y")`\
#'---
#'
#

#+ ---------------------------------
#' ## Loading libraries
library(plotly)
library(ggplot2)

#+ ---------------------------------
#' ## plotly example
#+ plotly,echo=FALSE,warning=FALSE,message=FALSE,error=FALSE,results='asis', plotly=TRUE

mtcars.p <- ggplot(mtcars, aes(mpg, wt, colour = cyl)) + geom_point() +
  labs(colour = "Cylinders")


iris.p <- ggplot(iris, aes(Petal.Length, Petal.Width, colour = Species)) + geom_point() +
  labs(colour = "Cylinders")

myPlots.l <- list(mtcars.p, iris.p)
names(myPlots.l) <- c("mtcars", "iris")

printPlots <- function(p, plots){
  cat("\n")
  cat("###", names(plots[p]))
  cat("\n")
  ggplotly(plots[[p]]) # this is not rendered
  cat("\n")
  print (plots[[p]]) # this is rendered, but of course this is not an interactive plot
  cat("\n")
}

cat("\n")
cat("## printing out of lapply -> plotly working")

cat("\n")
ggplotly(myPlots.l$mtcars) # this is rendered

cat("\n")
ggplotly(myPlots.l$iris) # this is also rendered
cat("\n")

cat("\n")
cat("## printing inside of lapply -> plotly not working")
cat("\n")
lapply(seq_along(myPlots.l), printPlots, myPlots.l )

The closer question to my problem is this one but I'm still stuck with this problem. Any idea how to solve this ?

here is my config :

R version 3.3.1 (2016-06-21)
Platform: x86_64-suse-linux-gnu (64-bit)
Running under: openSUSE Leap 42.2
2
I'm afraid you cannot produce an HTML widget (plotly) and an R graph next to each other in one step in lapply(). What you can possibly achieve is to produce all HTML widgets in one step, then all R graphs in another step. To achieve this, see stackoverflow.com/q/30509866/559676Yihui Xie
It is absolutely possible to have HTML and R graphs in the same document using any method. You simply need to ensure the plot is explicitly printed, not merely returned. ggplotly does not explicitly print the output.alan ocallaghan

2 Answers

1
votes

Here's a solution. You need to call knit_print() on "ggplotly" object (it's an htmlwidget object).
htmlwidgets needs to be attached.
The only problem I couldn't resolve is ggplotly width/height: I have to explicit these values.

#'---
#'author: "pokyah"
#'output: 
#'  html_document:
#'    theme: flatly
#'    toc: true
#'    toc_depth: 6
#'    toc_float:
#'      collapsed: false
#'      smooth_scroll: true
#'title: "Plotly test"
#'date: \`r format(Sys.Date(), " %d-%m-%Y")`\
#'---
#'
#

#+ ---------------------------------
#' ## Loading libraries
library(plotly)
library(ggplot2)
library(htmlwidgets)
library(knitr)

#+ ---------------------------------
#' ## plotly example
#+ plotly,echo=FALSE,warning=FALSE,message=FALSE,error=FALSE,results='asis', plotly=TRUE

mtcars.p <- ggplot(mtcars, aes(mpg, wt, colour = cyl)) + geom_point() +
  labs(colour = "Cylinders")


iris.p <- ggplot(iris, aes(Petal.Length, Petal.Width, colour = Species)) + geom_point() +
  labs(colour = "Cylinders")

myPlots.l <- list(mtcars.p, iris.p)
names(myPlots.l) <- c("mtcars", "iris")

printPlots <- function(p, plots){
  cat("\n")
  cat("###", names(plots[p]))
  cat("\n")
  #ggplotly(plots[[p]]) # this is not rendered. Of course, no "print" method is called.
                       # This line only returns an htmlwidget object that is lost because inside a function. 
  cat(knit_print(ggplotly(plots[[p]], width = 672, height = 480))) # This works.
  cat("\n")
  print(plots[[p]]) # this is rendered, but of course this is not an interactive plot
  cat("\n")
}

cat("\n")
cat("## printing out of lapply -> plotly working")

cat("\n")
ggplotly(myPlots.l$mtcars) # this is rendered

cat("\n")
ggplotly(myPlots.l$iris) # this is also rendered
cat("\n")

cat("\n")
cat("## printing inside of lapply -> plotly not working")
cat("\n")
lapply(seq_along(myPlots.l), printPlots, myPlots.l)
0
votes

I don't think there is a function render within knitr. However, if you want to produce a document with a mix of HTML and standard R plots, you could use an RMarkdown document such as the one below. You could then knit this and it will produce the desired output.

Also, regarding why the plotly plots are not showing? You need to call print on them in order for them to show, since you are calling ggplotly within a function.

---
author: "pokyah"
output: 
  html_document:
    theme: flatly
    toc: true
    toc_depth: 6
    toc_float:
      collapsed: false
      smooth_scroll: true
title: "Plotly test"
date: \`r format(Sys.Date(), " %d-%m-%Y")`\
---


# ---------------------------------
#' ## Loading libraries


#+ ---------------------------------
#' ## plotly example

```{r}
library(plotly)
library(ggplot2)
mtcars.p <- ggplot(mtcars, aes(mpg, wt, colour = cyl)) + geom_point() +
  labs(colour = "Cylinders")


iris.p <- ggplot(iris, aes(Petal.Length, Petal.Width, colour = Species)) + geom_point() +
  labs(colour = "Cylinders")

myPlots.l <- list(mtcars.p, iris.p)
names(myPlots.l) <- c("mtcars", "iris")

printPlots <- function(p, plots){
  cat("\n")
  cat("###", names(plots[p]))
  cat("\n")
  print(ggplotly(plots[[p]])) # this is not rendered
  cat("\n")
  print (plots[[p]]) # this is rendered, but of course this is not an interactive plot
  cat("\n")
}

cat("\n")
cat("## printing out of lapply -> plotly working")

cat("\n")
ggplotly(myPlots.l$mtcars) # this is rendered

cat("\n")
ggplotly(myPlots.l$iris) # this is also rendered
cat("\n")

cat("\n")
cat("## printing inside of lapply -> plotly not working")
cat("\n")
lapply(seq_along(myPlots.l), printPlots, myPlots.l )
```