1

I would like to save/download my barplots in shiny. I did it with ggplot, with ggsave and it was possible, but how can I do it for barplot()? My code in ui.R is:

library(shiny)
library(shinydashboard)
library(ggplot2)

ui <- dashboardPage(
  dashboardHeader(),
  dashboardSidebar(),
  dashboardBody(
    box(
      title = "", 
      status = "danger", 
      solidHeader = TRUE,
      plotOutput(outputId = "myPlotMdata1")
    ),

    box(
      title = "", 
      status = "danger", 
      solidHeader = TRUE,
      plotOutput(outputId = "myPlotMdata2")
    ),

    box(
      title = "", 
      status = "danger", 
      solidHeader = TRUE,
      plotOutput(outputId = "myPlotMdata3")
    ),

    box(
      title = "", 
      status = "danger", 
      solidHeader = TRUE,
      plotOutput(outputId = "myPlotMdata4")
    ),
    box(
      title = "Download", 
      status = "success", 
      solidHeader = TRUE,
      width = 12,
      radioButtons("formatTopwords", "Document format", c("PNG"="png", "EPS"="eps", "PDF"="pdf"), inline = TRUE),
      downloadButton("downloadReportTopwords")
    )
  )
) 

server <- function(input, output) {
  output$myPlotMdata1 <- renderPlot({
    barplot(TopWords$lassoInfPos, las = 2, names.arg = TopWords$informedPos, main = "Informed Investor Top 15 positive words", ylab = "Lasso coefficient")
  })

  output$myPlotMdata2 <- renderPlot({
    barplot(TopWords$lassoNoisePos , las = 2, names.arg = TopWords$noisePos, main = "Noise Investor Top 15 positive words", ylab = "Lasso coefficient")
  })

  output$myPlotMdata3 <- renderPlot({
    barplot(TopWords$lassoInfNeg, las = 2, names.arg = TopWords$informedNeg, main = "Informed Investor Top 15 negative words", ylab = "Lasso coefficient")
  })

  output$myPlotMdata4 <- renderPlot({
    barplot(TopWords$lassoNoiseNeg, las = 2, names.arg = TopWords$noiseNeg, main = "Noise Investor Top 15 negative words", ylab = "Lasso coefficient")
  })

  fn <- reactive({paste("Plot",input$formatTopwords,sep = ".")})
  d <- reactive({input$formatTopwords})

  output$downloadReportTopwords <- downloadHandler(
    filename = fn,
    content = function(file) {
      #ggsave I use for another function, how can I save barplots here
      ggsave(file, device=d(), dpi = 600, width = 297, height = 210, units = "mm")
    }
  )
}  

shinyApp(ui, server)
Karolis Koncevičius
  • 9,417
  • 9
  • 56
  • 89
Belfort90
  • 39
  • 1
  • 9
  • You're app is not reproducible, there is no data and no barplots. Could you include some dummy data.. – SeGa Jun 13 '18 at 20:24
  • @SeGa check now. But the important task is the download of the plot. My dataframe includes 70.000 rows so I cant include dummy data – Belfort90 Jun 13 '18 at 20:30
  • I know, but without a functioning app, everyone has to write his own dummy data to check if its working, except someone has a solution already. There is no need to add your data.frame, just create a random one, with maybe only one numeric column and just include one barplot. Thats gonna make it much easier to go through the code and focus on the important stuff. – SeGa Jun 13 '18 at 20:36
  • Possible duplicate of [How to make a great R reproducible example?](https://stackoverflow.com/questions/5963269/how-to-make-a-great-r-reproducible-example) – Belfort90 Jun 15 '18 at 11:43

1 Answers1

0

I'm not sure about EPS, but the following example works for PNG and PDF. You can create a plotting function, which you then call in your renderPlot and in the downloadHandler.

library(shiny)
library(shinyjs)
library(shinydashboard)
library(ggplot2)

TopWords = data.frame(
  lassoInfPos = runif(100,1,100),
  lassoNoisePos = runif(100,1,50),
  lassoInfNeg = runif(100,1,20),
  lassoNoiseNeg = runif(100,1,10)
)

ui <- {dashboardPage(
  dashboardHeader(),
  dashboardSidebar(),
  dashboardBody(
    box(width = 6,
      plotOutput("myPlotMdata1"),
      plotOutput("myPlotMdata2")
    ),
    box(width = 6,
      plotOutput("myPlotMdata3"),
      plotOutput("myPlotMdata4")
    ),
    box(
      title = "Download", 
      status = "success", 
      solidHeader = TRUE,
      width = 12,
      radioButtons("formatTopwords", "Document format", c("PNG"="png", "EPS"="eps", "PDF"="pdf"), inline = TRUE),
      downloadButton("downloadReportTopwords")
    )
  )
)}



barplot_func <- function(input, main) {
  barplot(input, las = 2, #names.arg = TopWords$informedPos, 
          main = main, ylab = "Lasso coefficient")
}

server <- function(input, output) {
  output$myPlotMdata1 <- renderPlot({
    barplot_func(TopWords$lassoInfPos, "Informed Investor Top 15 positive words")
  })
  output$myPlotMdata2 <- renderPlot({
    barplot_func(TopWords$lassoNoisePos, "Informed Investor Top 15 positive words")
  })
  output$myPlotMdata3 <- renderPlot({
    barplot_func(TopWords$lassoInfNeg, "Informed Investor Top 15 negative  words")
  })
  output$myPlotMdata4 <- renderPlot({
    barplot_func(TopWords$lassoNoiseNeg, "Informed Investor Top 15 negative  words")
  })

  fn <- reactive({paste("Plot",input$formatTopwords,sep = ".")})
  d <- reactive({input$formatTopwords})

  output$downloadReportTopwords <- downloadHandler(
    filename = fn,
    content = function(file) {
      if (input$formatTopwords == "png") {
        png(file)
      } else if(input$formatTopwords == "pdf") {
        pdf(file)
      }
      par(mfrow=c(2,2))
      barplot_func(TopWords$lassoInfPos, "Informed Investor Top 15 positive words")
      barplot_func(TopWords$lassoNoisePos, "Informed Investor Top 15 positive words")
      barplot_func(TopWords$lassoInfNeg, "Informed Investor Top 15 negative  words")
      barplot_func(TopWords$lassoNoiseNeg, "Informed Investor Top 15 negative  words")
      dev.off() 
    }
  )
}  

shinyApp(ui, server)
SeGa
  • 9,454
  • 3
  • 31
  • 70
  • perfect bro! it works nicely! thanks so much. But I am ploting 4 different barplots. is it also possible to download all together, like all in one page? – Belfort90 Jun 13 '18 at 21:02
  • Yes you can, I just edited my answer, although thats the ugly way of doing that. But you can set par(mfrow()) to whatever you like and then add all the plots in there. But I would actually create a plotting function, which creates the barplot with certain arguments, then you would just have to call the function in the `renderPlot` function and in the `downloadHandler`. – SeGa Jun 13 '18 at 21:07
  • I edited the answer. Its much nicer with a plotting function. :) – SeGa Jun 13 '18 at 21:18
  • thanks so much, just perfect! Have a look on my other problem, where I cant solve it :/ https://stackoverflow.com/questions/50856951/subset-dataframe-and-plot-with-ggplot – Belfort90 Jun 14 '18 at 11:54