【问题标题】:Problem with Shiny downloadHandler - Won't Download Filtered Data as Displayed on ScreenShiny downloadHandler 的问题 - 不会下载屏幕上显示的过滤数据
【发布时间】:2021-07-26 08:33:28
【问题描述】:

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

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

问题在于,在引用链接中的示例代码中,以及在我的情况下,过滤器都按应有方式应用于屏幕上的数据表,但是当通过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)

【问题讨论】:

  • 你试过我的答案了吗?
  • 是的,谢谢您-当您的回答通过时,我正在睡觉。 :) 您的答案被接受为解决方案。

标签: r shiny dt


【解决方案1】:

您没有以正确的方式使用响应式对象。在 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)


【讨论】:

  • 非常感谢约翰!是的,我知道 reactiveDF 是解决方案的关键,但我错过了如何将其包装到过滤条件中的联系。你总结的很到位。我最终测试了代码,它完全可以正常工作。
猜你喜欢
  • 2016-05-05
  • 2021-09-03
  • 2020-04-30
  • 2021-11-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-04-02
  • 2023-03-05
相关资源
最近更新 更多