1

Why does renderImage() not recognize input in the code sample below:

library(d3heatmap)
library(shiny)
library(ggplot2)


    ui <- fluidPage(
      h1("A heatmap demo"),
      selectInput("palette", "Palette", c("YlOrRd", "RdYlBu", "Greens", "Blues")),
      checkboxInput("cluster", "Apply clustering"),
      downloadButton('downloadPlot', 'Download Heatmap'),
      d3heatmapOutput("heatmap")
)

    server <- function(input, output, session) {

      output$heatmap <- renderD3heatmap({
        d3heatmap(
          scale(mtcars),
          colors = input$palette,
          dendrogram = if (input$cluster) "both" else "none"
) })

    output$downloadPlot <- renderImage(
        d3heatmap(scale(mtcars), colors = input$palette, dendrogram = if (input$cluster) "both" else "none"), 
        env = parent.frame(), 
        quoted = FALSE, 
        deleteFile = FALSE
        )

    }

shinyApp(ui = ui, server = server)

This is my error:

Error in match.arg(dendrogram) : object 'input' not found

When I remove the dendrogram = if (input$cluster) "both" else "none" line, I get the following error concerning input again:

Error in toPaletteFunc(pal) : object 'input' not found

It seems a bit counterintuitive that the object input isn't found, as I've explicitly defined it upstairs with: server <- function(input, output, session).

I've already examined existing Stack Overflow posts that generate a similar error message (e.g., R Shiny error: object input not found).

Code sample above was inspired by: https://cran.r-project.org/web/packages/d3heatmap/d3heatmap.pdf

Community
  • 1
  • 1
warship
  • 2,924
  • 6
  • 39
  • 65

1 Answers1

3

d3heatmap() produce the htmlwidgets class object. We can use saveWidget() function from the htmlwidgets package to save plot.

library(d3heatmap)
library(shiny)
library(htmlwidgets)

ui <- fluidPage(
    h1("A heatmap demo"),
    selectInput("palette", "Palette", c("YlOrRd", "RdYlBu", "Greens", "Blues")),
    checkboxInput("cluster", "Apply clustering"),
    downloadButton('download', 'Download Heatmap'),
    d3heatmapOutput("heatmap")
)
server <- function(input, output, session) {
    plot <- reactive({
        d3heatmap(
            scale(mtcars),
            colors = input$palette,
            dendrogram = if (input$cluster) "both" else "none"
        )
    })
    output$heatmap <- renderD3heatmap({
        plot()
    })
    output$download <- downloadHandler(
        filename = function() {
            paste0("d3heatmap-", tolower(input$palette), ".html")
        },
        content = function(file) {
            saveWidget(plot(), file)
        }
    )
}

shinyApp(ui = ui, server = server)

If you need save a plot as png see this discussion: https://github.com/ramnathv/htmlwidgets/issues/95. In short: now htmlwidgets does not support export plots as png or svg. You can see exportwidget and webshot packages as workground.

Artem Klevtsov
  • 9,193
  • 6
  • 52
  • 57
  • Accepted and also +1 from me for very nice, clean code. Would it be possible for you to show if there is a way to export a plot as pdf/jpg/tiff/etc? I understand that png/svg are off the table, but maybe there is a clever way to produce one of these alternatives. – warship Dec 27 '15 at 10:15
  • 1
    I think exportwidget library would be much more promising than webshot for this specific question because the code of exportwidget looks cleaner IMHO, which would make a perfect companion to this R code. However, I'm having a bit of trouble understanding how to adapt exportwidget's R code to this specific question, as they seem to be doing much more complex things (e.g., multiple htmlwidgets, digraphs, etc). – warship Dec 27 '15 at 10:46