Home > OS >  Choose which plot I want to download from Shiny app
Choose which plot I want to download from Shiny app

Time:07-24

I want to adapt this code to be able to choose which plot I want to download in pdf format. I have tried to assign the plot to an object called "p1" for plot1 and "p2" for plot2 and then call the objects in each condition but it doesn't work. The only way it works is as it is now that I put the complete function of the plot, but I can't choose which of the two.

I also want to put the download button inside the sidebarPanel but then it stops working. How can I make it to be in the sidebar?

library(shiny)

# Define UI for application that draws a histogram
ui <- fluidPage(
  titlePanel("Download base plot in Shiny - an example"),
  sidebarLayout(
    sidebarPanel(
      selectInput(inputId = "var1", label = "Select the X variable", choices = c("Sepal.Length" = 1, "Sepal.Width" = 2, "Petal.Length" = 3, "Petal.Width" = 4)),
      selectInput(inputId = "var2", label = "Select the Y variable", choices = c("Sepal.Length" = 1, "Sepal.Width" = 2, "Petal.Length" = 3, "Petal.Width" = 4), selected = 2),
      radioButtons(inputId = "var3", label = "Select the plot", choices = list("plot1", "plot2"))
    ),
    mainPanel(
      plotOutput("plot"),
      plotOutput("plot2"),
      downloadButton(outputId = "down", label = "Download the plot")
    )
  )
  
)

# Define server logic required to draw a histogram
server <- function(input, output) {
  # x contains all the observations of the x variable selected by the user. X is a reactive function
  x <- reactive({
    iris[,as.numeric(input$var1)]
  })
  # x contains all the observations of the y variable selected by the user. Y is a reactive function
  y <- reactive({
    iris[,as.numeric(input$var2)]
    
  })
  # xl contains the x variable or column name of the iris dataset selected by the user
  xl <- reactive({
    names(iris[as.numeric(input$var1)])
  })
  # yl contains the y variable or column name of the iris dataset selected by the user
  yl <- reactive({
    names(iris[as.numeric(input$var2)])
  })
  
  # render the plot so could be used to display the plot in the mainPanel
  output$plot <- renderPlot({
    plot(x=x(), y=y(), main = "iris dataset plot", xlab = xl(), ylab = yl())
  })
  
  # render the plot so could be used to display the plot in the mainPanel
  output$plot2 <- renderPlot({
    plot(x=x(), y=y(), main = "iris plot 2", xlab = xl(), ylab = yl(), col = "blue")
  })
  
  # downloadHandler contains 2 arguments as functions, namely filename, content
  output$down <- downloadHandler(
    filename =  function() {
      paste("iris", input$var3, sep=".")
    },
    # content is a function with argument file. content writes the plot to the device
    content = function(file) {
      if(input$var3 == "plot1")
        pdf(file) # open the png device
      # if(input$var3 == "png2")
      #   pdf(file)
      else
        pdf(file) # open the pdf device
      plot(x=x(), y=y(), main = "iris dataset plot", xlab = xl(), ylab = yl())
      dev.off()  # turn the device off
    } 
  )
  
}

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

CodePudding user response:

You can use recordPlot() to put the plot in an object and replayPlot() in an opened device:

library(shiny)

# Define UI 
ui <- fluidPage(
  titlePanel("Download base plot in Shiny - an example"),
  sidebarLayout(
    sidebarPanel(
      selectInput(
        inputId = "var1", label = "Select the X variable", 
        choices = c(
          "Sepal.Length" = 1, 
          "Sepal.Width" = 2, 
          "Petal.Length" = 3, 
          "Petal.Width" = 4
        )
      ),
      selectInput(
        inputId = "var2", label = "Select the Y variable", 
        choices = c(
          "Sepal.Length" = 1, 
          "Sepal.Width" = 2, 
          "Petal.Length" = 3, 
          "Petal.Width" = 4
        ), 
        selected = 2
      ),
      radioButtons(
        inputId = "var3", label = "Select the plot", 
        choices = list("plot1", "plot2")
      )
    ),
    mainPanel(
      plotOutput("plot"),
      plotOutput("plot2"),
      downloadButton(outputId = "down", label = "Download the plot")
    )
  )
  
)

# Define server logic required to draw a histogram
server <- function(input, output) {
  # x contains all the observations of the x variable selected by the user. X is a reactive function
  x <- reactive({
    iris[, as.numeric(input$var1)]
  })
  # x contains all the observations of the y variable selected by the user. Y is a reactive function
  y <- reactive({
    iris[, as.numeric(input$var2)]
    
  })
  # xl contains the x variable or column name of the iris dataset selected by the user
  xl <- reactive({
    names(iris[as.numeric(input$var1)])
  })
  # yl contains the y variable or column name of the iris dataset selected by the user
  yl <- reactive({
    names(iris[as.numeric(input$var2)])
  })
  
  Plot1 <- reactive({
    plot(
      x=x(), y=y(), main = "iris dataset plot", xlab = xl(), ylab = yl()
    )
    recordPlot()
  })
  
  Plot2 <- reactive({
    plot(
      x=x(), y=y(), main = "iris plot 2", xlab = xl(), ylab = yl(), col = "blue"
    )
    recordPlot()
  })
  
  # render the plot so could be used to display the plot in the mainPanel
  output$plot <- renderPlot({
    Plot1()
  })
  
  # render the plot so could be used to display the plot in the mainPanel
  output$plot2 <- renderPlot({
    Plot2()
  })
  
  # downloadHandler contains 2 arguments as functions, namely filename, content
  output$down <- downloadHandler(
    filename =  function() {
      paste("iris", input$var3, "pdf", sep=".")
    },
    # content is a function with argument file. content writes the plot to the device
    content = function(file) {
      if(input$var3 == "plot1"){
        pdf(file)
        replayPlot(Plot1())
        dev.off()
      }else{
        pdf(file)
        replayPlot(Plot2())
        dev.off()
      }  
    } 
  )
  
}

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