如何从筛选数据表 (DT) 的选定行中获取数据?

How do I get the data from the selected rows of a filtered datatable (DT)?

DT 包允许您使用 input$tableID_rows_selected 获取选定行的索引。这对于没有过滤数据的表非常有用。但是,如果我们有过滤后的数据集,我们就不能使用相同的方法,因为行索引已关闭。

那么对于过滤后的数据集,我们如何获取数据表中选中行的数据呢?

下面,我发布了一个基本的 shiny 应用程序,它显示了四个表:第一个是原始 mtcars 数据集,第二个获取第一个中的选定行。第三个和第四个做同样的事情,但是在 "filter" sliderInput.

上过滤数据集之后
library(shiny)
library(DT)
library(dplyr)

ui <- fluidPage(
  DT::dataTableOutput("origTable"),
  DT::dataTableOutput("origTableSelected"),
  sliderInput("filter", label = "Filter by cyl", min = 4, max = 8, step = 2, value = 6),
  DT::dataTableOutput("filteredTable"),
  DT::dataTableOutput("filteredTableSelected")
)


server <- function(input, output, session) {

  output$origTable <- DT::renderDataTable({
    datatable(
      mtcars,
      selection = list(mode = "multiple"),
      caption = "Original Data"
    )
  })

  origTable_selected <- reactive({
    ids <- input$origTable_rows_selected
    mtcars[ids,]
  })

  output$origTableSelected <- DT::renderDataTable({
    datatable(
      origTable_selected(),
      selection = list(mode = "multiple"),
      caption = "Selected Rows from Original Data Table"
    )
  })

  output$filteredTable <- DT::renderDataTable({
    datatable(
      filter(mtcars, cyl == input$filter),
      selection = list(mode = "multiple"),
      caption = "Filtered Table (based on cyl)"
    )
  })

  filteredTable_selected <- reactive({
    ids <- input$filteredTable_rows_selected
    mtcars[ids,]
  })

  output$filteredTableSelected <- DT::renderDataTable({
    datatable(
      filteredTable_selected(),
      selection = list(mode = "none"),
      caption = "Table that gets data from unfiltered original data"
    )
  })
}

shinyApp(ui = ui, server = server)

一种方法:在您的 filteredTable_selected() 函数中,您正在创建将放入第四个 DT 的数据,使用 filter(mtcars, cyl == input$filter) 就像您对第三个 [=18] 所做的那样=] 而不是 mtcars。这样,行索引将匹配。

如果您担心较大数据集的性能问题,只需在缓存其输出的反应式表达式中过滤数据即可。这样,您过滤的内容不会超过您的 input$filter 值更改。

server <- function(input, output, session) {
  filteredTable_data <- reactive({
    filter(mtcars, cyl == input$filter)
  })

  output$filteredTable <- DT::renderDataTable({
    datatable(
      filteredTable_data(),
      selection = list(mode = "multiple"),
      caption = "Filtered Table (based on cyl)"
    )
  })

  filteredTable_selected <- reactive({
    ids <- input$filteredTable_rows_selected
    filteredTable_data()[ids,]
  })

  output$filteredTableSelected <- DT::renderDataTable({
    datatable(
      filteredTable_selected(),
      selection = list(mode = "none"),
      caption = "Table that gets data from unfiltered original data"
    )
  })
}

虽然接受的答案为 shiny 提供了一个可行的解决方案,但如何在 flexdashboard 的 R Markdown 文档中实现它并不明显。

Rmd文档中,render*()DT::renderDataTable()这样的函数通常是匿名使用的,但是possible显式地将它们赋值到output槽中shiny。在这种情况下,要使用 input$tableID_rows_selected 结构,就必须这样做。

此解决方案还对索引进行排序,以始终保持与原始数据框中相同的顺序。

---
title: "MRE"
author: ""
output: 
  flexdashboard::flex_dashboard:
    orientation: columns
    vertical_layout: scroll
runtime: shiny
---

Page {data-orientation=columns}
=======================================================================

Column {data-width=650}
-----------------------------------------------------------------------

### .

```{r}
  require(DT)
  library(dplyr)
  library(tibble)

  sliderInput("filter", label = "Filter by cyl", min = 4, max = 8, step = 2, value = 6)


  filteredTable_data <- reactive({
    mtcars %>% rownames_to_column() %>%  ##dplyr's awkward way to preserve rownames
          filter(., cyl == input$filter) %>% column_to_rownames()
  })

  ##explicit assignment to output ID
  DT::dataTableOutput("filteredTable")
  output$filteredTable <- DT::renderDataTable({
    datatable(
      filteredTable_data(),
      selection = list(mode = "multiple"),
      caption = "Filtered Table (based on cyl)"
    )
  })

  filteredTable_selected <- reactive({
    ids <- input$filteredTable_rows_selected
    filteredTable_data()[sort(ids),]  ##sort index to ensure orig df sorting
  })

  ##anonymous
  DT::renderDataTable({
    datatable(
      filteredTable_selected(),
      selection = list(mode = "none"),
      caption = "Table that gets data from unfiltered original data"
    )
  })

```

输出如下: