dracodoc
dracodoc

Reputation: 2763

ggplot in shiny app go to rstudio plot window

I have a shiny app that draw some ggplot2 plots in app. Now I’m making it into a package and export the plot drawing as a function. I found once I draw some ggplot in RStudio and start my shiny app, then all plots in my shiny app went to the RStudio plot pane.

I have tracked down the problem to very specific location and made a minimal working example.

This shiny app draw a ggplot, though it first save the ggplot into png with ggsave, then return the ggplot object to renderPlot so that it is shown in app.

library(shiny)
library(ggplot2)
SAVE_PLOT <- TRUE
ui <- fluidPage(fluidRow(column(12, plotOutput("plot"))))
server <- function(input, output){
  output$plot <- renderPlot({
    g <- ggplot(mtcars, aes(wt, mpg)) + geom_point()
    if (SAVE_PLOT) {
      ggsave("plot.png", g)
    }
    g
  })
}
shinyApp(ui = ui, server = server)

If I run this simple code in RStudio first

library(ggplot2)
ggplot(mtcars, aes(wt, mpg)) + geom_point()

then run the app above, the plot in app is shown in RStudio plot window.

If I set SAVE_PLOT <- FALSE then the app will have plot shown correctly. This show the problem is caused by ggsave.

I didn’t try if plot first and save it later will not have this problem, because the plot in my real app is reactive, plot it first means I need to wrap every plot into a reactive instead of just write in renderPlot.

If I run dev.off after the ggplot in console, the plot will not go to rstudio. Though this is obviously not a solution either.

According to ggsave code, it create a new device then turn off current device after saving. Is it possible that it actually messed up in this case and turned off the shiny plot device also?

It's also possible to be something with Shiny, or with RStudio.

UPDATE: the problem is not specific to RStudio, the R console have same problem.

Upvotes: 3

Views: 1658

Answers (2)

dracodoc
dracodoc

Reputation: 2763

Thanks for hints from @Claus Wilke, I don't think we should turn off the current device but we can save the device and restore it.

We can use this to work around the problem:

library(shiny)
library(ggplot2)
SAVE_PLOT <- TRUE
ui <- fluidPage(fluidRow(column(12, plotOutput("plot"))))
server <- function(input, output){
  output$plot <- renderPlot({
    g <- ggplot(mtcars, aes(wt, mpg)) + geom_point()
    if (SAVE_PLOT) {
      cur_dev <- dev.cur()
      ggsave("plot.png", g)
      dev.set(cur_dev)
    }
    g
  })
}
shinyApp(ui = ui, server = server)

Thanks to @wch, issue has been created in ggplot2 repo since it's a ggsave bug.

Upvotes: 2

Claus Wilke
Claus Wilke

Reputation: 17790

Enclosing the ggsave() function in pdf(NULL); ggsave(...); dev.off() seems to provide a workaround here, though sometimes the graphics device is in strange state when closing the app.

library(shiny)
library(ggplot2)
SAVE_PLOT <- TRUE
ui <- fluidPage(fluidRow(column(12, plotOutput("plot"))))
server <- function(input, output){
  output$plot <- renderPlot({
    g <- ggplot(mtcars, aes(wt, mpg)) + geom_point()
    if (SAVE_PLOT) {
      pdf(NULL)
      ggsave("plot.png", g)
      dev.off()
    }
    g
  })
}
qplot(1:10, 1:10) # shows up in R Studio window
shinyApp(ui = ui, server = server) # shows up in shiny window

Upvotes: 0

Related Questions