0

I am developing a package in R and its plotting functions include a line with pdf() or png() to save the figure. However, when I tried to create a Shiny app from this package the plots did not appear on the app. I verified that the pdf() function prevents the plot from being displayed. Is there a way to show the plots without changing the whole package? I was thinking about saving the image and rendering it, but maybe there is a more efficient answer.

I created a sample code just to illustrates the problem. The test_plot function shows an example of the structure of the functions in my package.

test_plot <- function(){
    data=head(mtcars, 30)
    
    g1 <- ggplot(data, aes(x=wt, y=mpg)) +
        geom_point() + # Show dots
        geom_text(
            label=rownames(data), 
            nudge_x = 0.25, nudge_y = 0.25, 
            check_overlap = T
        )
    pdf(file = 'test.pdf', width = 5, height = 5)
    print(g1)
}

The renderPlot just calls the test_plot. If I remove the pdf() from the code the figure is displayed correctly.

server <- function(input, output) {
    output$distPlot <- renderPlot({
        test_plot()
    })
}
Rafael
  • 193
  • 5
  • Can you return the `g1` in `test_plot` and then use `pdf` outside the function – akrun Aug 30 '21 at 21:37
  • 2
    You need to send the output to the proper display; when PDF or PNG are opened, the plot gets sent to those. You cannot avoid that to my knowledge. – TARehman Aug 30 '21 at 21:38
  • Are you trying to render it as an actual image in your shiny application? Or are you trying to embed a PDF viewer? Have the plotting function automatically write to a PDF really is problematic. Rendering and saving the image should be separate steps. If you want it to be more web-friendly, you'd need to [convert the PDF to something like PNG](https://stackoverflow.com/questions/18617270/convert-pdf-to-png-in-r) for easier display in a website. – MrFlick Aug 30 '21 at 22:04
  • I already have functions that directly save the plots in pdf files, in a regular R package. However, I couldn't use these functions in the Shiny app due to the pdf() line. – Rafael Aug 30 '21 at 22:17

1 Answers1

0

Perhaps try separating the renderPlot() from the PNG file itself, and allow the user to download the PNG with a downloadHandler():

library(shiny)
library(tidyverse)

# Define UI for application that draws a histogram
ui <- fluidPage(

    # Sidebar with a slider input for number of bins 
    sidebarLayout(
        sidebarPanel(
            sliderInput(
                inputId = "n", label = "Select rows",
                min = 1, max = nrow(mtcars), 
                value = 20, round = TRUE
            ),
            downloadButton(outputId = "download")),

        # Show a plot of the generated distribution
        mainPanel(plotOutput("plot"))
    )
)

# Define server logic required to draw a histogram
server <- function(input, output) {

    # render plot
    plot_reactive <- reactive({
        p <- head(mtcars, input$n) %>% 
            ggplot(aes(x = wt, y = mpg)) +
            geom_point() 
    })
    
    output$plot <- renderPlot(print(plot_reactive()))
    
    # download plot
    output$download <- downloadHandler(
        filename = function(){ paste0(input$n, "_mtcars.png") },
        content  = function(file){ ggsave(file, plot_reactive()) }
    )
}

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

Rich Pauloo
  • 7,734
  • 4
  • 37
  • 69