简体   繁体   中英

Downloading the outputs of a reactive table in R shiny

I have an R shiny app that gets a.csv import from a user and searches the imported data across a built-in data frame, then gives the % match in the output. The UI is very simple, with a few different inputs (import.csv, a slider, and some radio buttons). What I want is to be able to take the reactive table output and print this to a.csv that the user can download to their machine. The server side of the app looks something like this:

server <- function(input, output){
    rvals <- reactiveValues()

    observeEvent(input$file_1,{
        req(input$file_1)
        rvals$csv <<- read.csv(input$file_1$datapath, header = TRUE)
        #some data processing here
  })

    output$contents <- renderTable({
        if(input$select == 1){
        x <- function
        }else if(input$select == 2){
        x <- function
        }else if(input$select == 3){x <- function}

        #some more data processing and formatting here

        return(x)

    },digits = 4)
}

I would like to have the data table x be able to become a.csv that can be downloaded by clicking a download button. In the server, I added the following code, but when I try to download the data it just downloads a blank file and says "SERVER ERROR" in my downloads manager on my machine.

output$downloadData <- downloadHandler(
    filename = "thename.csv",
    content = function(file){
      write.csv(x, file)
    }

In the console I also get the error message: Warning: Error in is.data.frame: object 'x' not found [No stack trace available]

The object you create inside the expression of renderTable is not available outside of it. Instead you could assign it to the reactive values you set up. Below is a working example (note that I have tried to replicate your code so the data will not be available until you click on "Upload CSV", which here just calls mtcars ).

library(shiny)

ui = fluidPage(

  sidebarPanel(
    actionButton(inputId = "uploadCsv", label = "Upload CSV:", icon = icon("upload")),
    selectInput(inputId = "preProc", label = "Pre-processing", choices = c("Mean"=1,"Sum"=2)),
    downloadButton("downloadData", label = "Download table")
  ),

  mainPanel(
    h4("My table:"),
    tableOutput("contents")
  )

)

server <- function(input, output) {

  rvals <- reactiveValues(
    csv=NULL,
    x=NULL
  )

  observeEvent(input$uploadCsv,{
    rvals$csv <- mtcars # using example data since I don't have your .csv
    # rvals$csv <- read.csv(input$file_1$datapath, header = TRUE) 
    #some data processing here
  })

  output$contents <- renderTable({
    # Assuing the below are functions applied to your data
    req(
      input$preProc,
      !is.null(rvals$csv)
    )
    if(input$preProc == 1){
      rvals$x <- data.frame(t(colMeans(mtcars)))
    }else {
      rvals$x <- data.frame(t(colSums(mtcars)))
    }

    return(rvals$x)

  },digits = 4)

  output$downloadData <- downloadHandler(
    filename = "myFile.csv",
    content = function(file){
      write.csv(rvals$x, file)
    }
  )
}

shinyApp(ui,server)

EventReactive already outputs a reactive value, you don't need to create an extra reactiveVal, see example below:

library(shiny)

# Define UI
ui <- fluidPage(

  # Application title
  titlePanel("Test"),
    mainPanel(
      actionButton("show", "Download"),
      textOutput("result")
    )
  )


server <- function(input, output) {
  csvfile <- eventReactive(req(input$show), ignoreNULL = T, {
      "Content of file"
   })

  output$result <-  reactive(
    paste("result : ",csvfile()))
}

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

I would also avoid to use <<- operator in a reactive expression.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM