首页 > 解决方案 > Shiny downloadHandler 的问题 - 不会下载屏幕上显示的过滤数据

问题描述

我正在尝试将如下所示的相同基本(可重现)代码应用于我的应用程序,正如在此问题上找到的此测试示例(并使用提供的解决方案)中提供的那样:从 Shiny 中的 renderDatatable 下载数据

我对其进行了一些定制,以便表格使用selectInput()过滤器,而不是在呈现时显示在数据表顶部的过滤器。

问题是,在引用链接中的示例代码中,以及在我的情况下,过滤器都应该应用于屏幕上的数据表,但是当通过 时downloadHandler()它不会导出过滤后的数据。它过滤掉过滤的正确行,但它不是正确的数据。

我正在努力想出一个解决方案,以便在下载文件时将我打算成为“反应式”应用程序的应用程序应用于表,以便期望的结果是导出的数据是在应用程序中过滤的实际数据。

library(shiny)
library(DT)
library(ggplot2)


## === LOAD EXAMPLE DATA =====

cars = mtcars


# do I make the data frame reactive?

reactiveDF = reactive(cars)

## ==== UI ====

ui <- fluidPage(
  titlePanel("Basic DataTable"),
  
  # Create a new Row in the UI for selectInputs
  fluidRow(
    column(4,
           selectInput("cyl",
                       "Cylinders:",
                       c("All",
                         unique(sort(as.character(cars$cyl)))))
    ),
    column(4,
           selectInput("gear",
                       "Gears:",
                       c("All",
                         unique(as.character(cars$gear))))
    ),
    column(4,
           selectInput("carb",
                       "Carburators:",
                       c("All",
                         unique(as.character(cars$carb))))
    )
  ),
  # Create a new row for the table.
  
  DT::dataTableOutput("dt"),
  
  p("Notice that the 'rows_all' attribute grabs the row indices of the data."),
  verbatimTextOutput("filtered_row"),
  
  # Create a new row for the download button
  p("The table responds to the filters perfectly, yet it will not download the data. Test it out."),
  p("Evaluate the csv file and you will see that while it extracts the filtered rows,"),
  p("it is not displaying the actual filtered data in the table!"),
  
  downloadButton(outputId = "download_filtered",
                 label = "Download Filtered Data")
)


## ==== END UI ====

## ==== SERVER ====

server = function(input, output){
  
  output$filtered_row <- 
    renderPrint({
      input[["dt_rows_all"]]
    })
  
  # Filter data based on selections
  
  # This controls the 3 filters displayed on top of the datatable
  output$dt <- DT::renderDataTable(datatable({
    cardata <- cars
    # conditionals 
    
    if (input$cyl != "All") {
      cardata <- cardata[cardata$cyl == input$cyl, ]
    }
    if (input$gear != "All") {
      cardata <- cardata[cardata$gear == input$gear, ]
    }
    if (input$carb != "All") {
      cardata <- cardata[cardata$carb == input$carb, ]
    }
    
    # display the filtered data
    cardata
  }))
  
  
  
# Download handler for exporting the data to csv -this won't work as intended -----
  
  output$download_filtered <- 
    downloadHandler(
      filename = "filtered_report.csv",
      content = function(file){
        write.csv(cardata[input[["dt_rows_all"]], ],file)
      }
    )
}

shinyApp(ui,server)

标签: rshinydt

解决方案


您没有以正确的方式使用反应对象。在 Shiny 中,这种类型的对象背后的想法是避免重复自己。在这里,您可以创建一个响应式对象reactiveDF并使用该对象来生成 dataTableOutput 和下载表。

library(shiny)
library(DT)
library(ggplot2)


## === LOAD EXAMPLE DATA =====

cars = mtcars


# do I make the data frame reactive?



## ==== UI ====

ui <- fluidPage(
  titlePanel("Basic DataTable"),
  
  # Create a new Row in the UI for selectInputs
  fluidRow(
    column(4,
           selectInput("cyl",
                       "Cylinders:",
                       c("All",
                         unique(sort(as.character(cars$cyl)))))
    ),
    column(4,
           selectInput("gear",
                       "Gears:",
                       c("All",
                         unique(as.character(cars$gear))))
    ),
    column(4,
           selectInput("carb",
                       "Carburators:",
                       c("All",
                         unique(as.character(cars$carb))))
    )
  ),
  # Create a new row for the table.
  
  DT::dataTableOutput("dt"),
  
  p("Notice that the 'rows_all' attribute grabs the row indices of the data."),
  verbatimTextOutput("filtered_row"),
  
  # Create a new row for the download button
  p("The table responds to the filters perfectly, yet it will not download the data. Test it out."),
  p("Evaluate the csv file and you will see that while it extracts the filtered rows,"),
  p("it is not displaying the actual filtered data in the table!"),
  
  downloadButton(outputId = "download_filtered",
                 label = "Download Filtered Data")
)


## ==== END UI ====

## ==== SERVER ====

server = function(input, output){
  
  
  reactiveDF = reactive({
    cardata <- cars
    # conditionals 
    
    if (input$cyl != "All") {
      cardata <- cardata[cardata$cyl == input$cyl, ]
    }
    if (input$gear != "All") {
      cardata <- cardata[cardata$gear == input$gear, ]
    }
    if (input$carb != "All") {
      cardata <- cardata[cardata$carb == input$carb, ]
    }
    
    # display the filtered data
    cardata
    
    
  })
  
  output$filtered_row <- 
    renderPrint({
      input[["dt_rows_all"]]
    })
  
  # Filter data based on selections
  
  # This controls the 3 filters displayed on top of the datatable
  output$dt <- DT::renderDataTable(datatable({
    reactiveDF()
  }))
  
  
  
  # Download handler for exporting the data to csv -this won't work as intended -----
  
  output$download_filtered <- 
    downloadHandler(
      filename = "filtered_report.csv",
      content = function(file){
        write.csv(reactiveDF(),file)
      }
    )
}

shinyApp(ui,server)



推荐阅读