Problem in downloading the plot with downloadhandler for shiny app

I have some example data like below:

df <- structure(list(Samples = structure(1:10, .Label = c("Sample1", 
"Sample10", "Sample2", "Sample3", "Sample4", "Sample5", "Sample6", 
"Sample7", "Sample8", "Sample9"), class = "factor"), Type = structure(c(2L, 
1L, 2L, 2L, 2L, 1L, 2L, 2L, 1L, 1L), .Label = c("Normal", "Tumor"
), class = "factor"), A1BG = c(0, 0.01869105, 0.026705782, 0.016576987, 
0, 0.007636787, 0.015756547, 0.00609601, 0.115575528, 0.04717536
), A1BG.AS1 = c(0, 0.096652515, 0.086710002, 0.04683499, 0.188283185, 
0.104318353, 0.102735593, 0.100064808, 0.04717536, 0.159745808
), A1CF = c(1.616942802, 1.367084444, 1.101855892, 1.3823884, 
0.631627098, 2.407159505, 1.687449785, 1.229844138, 0.87989414, 
0.642785868), A2M = c(3.357654845, 3.149165846, 3.654774122, 
2.851143092, 2.952601867, 4.002335454, 4.123949457, 3.691343955, 
3.553064673, 3.425443559), A2M.AS1 = c(0.217308191, 0.08268571, 
0.297320544, 0.101579093, 0.020102613, 0.35578965, 0.288014115, 
0.145352771, 0.043808388, 0.104677012), A2ML1 = c(0, 0.017949113, 
0.00984907, 0.002289616, 0, 0.002100359, 0.032146138, 0.052275569, 
0.537892142, 0), A2ML1.AS1 = c(0.631627098, 0.04717536, 1.229844138, 
0, 4.002335454, 0, 1.229844138, 1.229844138, 0.04717536, 0)), row.names = c(NA, 
-10L), class = "data.frame")

I started creating the shiny app using the below code, but when I downloaded the plot I don't see any figure there.

library(shiny)
library(reshape2)
library(ggplot2)
library(ggpubr)
library(EnvStats)

                                                                                                                                                                                                                                                                                                  -10L), class = "data.frame")
df.m <- reshape2::melt(df, c("Samples", "Type"))

ui <- fluidPage(
  sidebarLayout(
    sidebarPanel(
      selectInput("thegene", "Gene", choices = c("A2M", "A1CF", "A2MP1"), selected = "A2M"),
      radioButtons("colour","Colour of histogram",choices=c("red","green","blue"),selected="red"),
      width = 3
    ),
    mainPanel(
      plotOutput("boxplot"),
      downloadLink("downloadPlot", "Download Plot"),
      width = 9
    )
  )
)

server <- function(input, output, session) {
  
  alldat <- reactive({
    # this is not an efficient use of a reactive block: since it does
    # not depend on any dynamic data, it will fire only once, so if
    # your data is static then this might be a touch overkill ... but
    # the premise is that your `df.m` is data that can change based on
    # updating it (e.g., DB query) or user-uploaded data (e.g., CSV
    # upload)
    choices <- unique(df.m$variable)
    selected <- isolate(input$thegene)
    if (!selected %in% choices) selected <- choices[1]
    updateSelectInput(session, "thegene", choices = choices, selected = selected)
    df.m
  })
  
  dat <- reactive({
    x <- alldat()
    x[ x$variable == input$thegene,,drop=FALSE]
  })
  
  output$boxplot <- renderPlot({
    ggplot(data = dat(), aes(x = Type, y = value, fill = variable)) +
      geom_boxplot() +
      theme_bw(base_size = 14) + xlab("") + ylab("Expression logFPKM") +
      theme(axis.text=element_text(size=15, face = "bold", color = "black"),
            axis.title=element_text(size=15, face = "bold", color = "black"),
            strip.text = element_text(size=15, face = "bold", color = "black")) +
      scale_fill_manual(values = input$colour)
  })
  
  output$downloadPlot <- downloadHandler(
    filename = function(){paste(input$thegene, '.pdf', sep = '')},

    content = function(file){
      pdf(file, width = 5, height = 5)
      dat()
      dev.off()
    })
}

# Run the application 
shinyApp(ui = ui, server = server)

Any help is appreciated. Thank you.

Hi @beginner2. The reason why cannot download the plot because dat() is just the data frame, not the ggplot object. So, I suggest you store the plot and print it again in the downloadHandler. In the following code, I define a reactiveValues to store the ggplot object.

library(shiny)
library(reshape2)
library(ggplot2)
library(ggpubr)
library(EnvStats)

df <- structure(list(Samples = structure(1:10, .Label = c("Sample1", 
                                                          "Sample10", "Sample2", "Sample3", "Sample4", "Sample5", "Sample6", 
                                                          "Sample7", "Sample8", "Sample9"), class = "factor"), Type = structure(c(2L, 
                                                                                                                                  1L, 2L, 2L, 2L, 1L, 2L, 2L, 1L, 1L), .Label = c("Normal", "Tumor"
                                                                                                                                  ), class = "factor"), A1BG = c(0, 0.01869105, 0.026705782, 0.016576987, 
                                                                                                                                                                 0, 0.007636787, 0.015756547, 0.00609601, 0.115575528, 0.04717536
                                                                                                                                  ), A1BG.AS1 = c(0, 0.096652515, 0.086710002, 0.04683499, 0.188283185, 
                                                                                                                                                  0.104318353, 0.102735593, 0.100064808, 0.04717536, 0.159745808
                                                                                                                                  ), A1CF = c(1.616942802, 1.367084444, 1.101855892, 1.3823884, 
                                                                                                                                              0.631627098, 2.407159505, 1.687449785, 1.229844138, 0.87989414, 
                                                                                                                                              0.642785868), A2M = c(3.357654845, 3.149165846, 3.654774122, 
                                                                                                                                                                    2.851143092, 2.952601867, 4.002335454, 4.123949457, 3.691343955, 
                                                                                                                                                                    3.553064673, 3.425443559), A2M.AS1 = c(0.217308191, 0.08268571, 
                                                                                                                                                                                                           0.297320544, 0.101579093, 0.020102613, 0.35578965, 0.288014115, 
                                                                                                                                                                                                           0.145352771, 0.043808388, 0.104677012), A2ML1 = c(0, 0.017949113, 
                                                                                                                                                                                                                                                             0.00984907, 0.002289616, 0, 0.002100359, 0.032146138, 0.052275569, 
                                                                                                                                                                                                                                                             0.537892142, 0), A2ML1.AS1 = c(0.631627098, 0.04717536, 1.229844138, 
                                                                                                                                                                                                                                                                                            0, 4.002335454, 0, 1.229844138, 1.229844138, 0.04717536, 0)), row.names = c(NA, 
                                                                                                                                                                                                                                                                                                                                                                        -10L), class = "data.frame")
df.m <- reshape2::melt(df, c("Samples", "Type"))

ui <- fluidPage(
  sidebarLayout(
    sidebarPanel(
      selectInput("thegene", "Gene", choices = c("A2M", "A1CF", "A2MP1"), selected = "A2M"),
      radioButtons("colour","Colour of histogram",choices=c("red","green","blue"),selected="red"),
      width = 3
    ),
    mainPanel(
      plotOutput("boxplot"),
      downloadLink("downloadPlot", "Download Plot"),
      width = 9
    )
  )
)

server <- function(input, output, session) {
  
  vals <- reactiveValues()
  
  alldat <- reactive({
    # this is not an efficient use of a reactive block: since it does
    # not depend on any dynamic data, it will fire only once, so if
    # your data is static then this might be a touch overkill ... but
    # the premise is that your `df.m` is data that can change based on
    # updating it (e.g., DB query) or user-uploaded data (e.g., CSV
    # upload)
    choices <- unique(df.m$variable)
    selected <- isolate(input$thegene)
    if (!selected %in% choices) selected <- choices[1]
    updateSelectInput(session, "thegene", choices = choices, selected = selected)
    df.m
  })
  
  dat <- reactive({
    x <- alldat()
    x[ x$variable == input$thegene,,drop=FALSE]
  })
  
  output$boxplot <- renderPlot({
    gg <- ggplot(data = dat(), aes(x = Type, y = value, fill = variable)) +
      geom_boxplot() +
      theme_bw(base_size = 14) + xlab("") + ylab("Expression logFPKM") +
      theme(axis.text=element_text(size=15, face = "bold", color = "black"),
            axis.title=element_text(size=15, face = "bold", color = "black"),
            strip.text = element_text(size=15, face = "bold", color = "black")) +
      scale_fill_manual(values = input$colour)
    
    vals$gg <- gg
    
    print(gg)
  })
  
  output$downloadPlot <- downloadHandler(
    filename = function(){paste(input$thegene, '.pdf', sep = '')},
    
    content = function(file){
      pdf(file, width = 5, height = 5)
      print(vals$gg)
      dev.off()
    })
}

# Run the application 
shinyApp(ui = ui, server = server)
2 Likes

Excellent thanks a lot raytong.

This topic was automatically closed 7 days after the last reply. New replies are no longer allowed.