在 Shiny 的反应函数中使用 dplyr 条件过滤器

Use dplyr conditional filter in reactive function in Shiny

我在 Shiny 应用反应函数中使用 dplyr。我在 UI 中有一个交互式小部件,用户可以使用它来 select 状态,数据将根据 selected 状态显示。但是我也想提供显示所有内容的选项,这是我称之为 'All'.

的状态

我知道如何在没有 dplyr 的情况下实现这一点:

library(tibble)
library(shiny)

# Test Data -----
test_data <- tribble(
  ~id, ~status,
  1, 'active',
  2, 'inactive',
  3, 'test'
)

# Ui ----
ui = fluidPage(
  selectInput("status", "Choose a status:",
              choices = list("All","active","inactive","test")
  ),
  tableOutput('result')
)

# Server ----
server = function(input, output) {

  table <- reactive({
    if(input$status != 'All')
    {
      test_data <- test_data[test_data$status == input$status,]
    } else {
      test_data
    }
  })

  output$result <- renderTable(table(), rownames = FALSE)

}

# App ---
shinyApp(ui = ui, server = server)

但是,我想与我的其余代码保持一致并使用 dplyr。有没有办法做类似下面的事情?

library(tibble)
library(dplyr)
library(shiny)

# Test Data -----
test_data <- tribble(
  ~id, ~status,
  1, 'active',
  2, 'inactive',
  3, 'test'
)

# Ui ----
ui = fluidPage(
  selectInput("status", "Choose a status:",
              choices = list("All","active","inactive","test")
  ),
  tableOutput('result')
)

# Server ----
server = function(input, output) {

  table <- reactive({
    test_data %>%
      filter(ifelse(input$status != 'All', status == input$status, status == ***pass***))
  })

  output$result <- renderTable(table(), rownames = FALSE)

}

# App ---
shinyApp(ui = ui, server = server)

换句话说,有没有办法在过滤函数中使用ifelse在特定条件下不过滤?

谢谢!

我不认为这是可能的。你可以这样做:

if(input$status!="All")
  test_data %>% filter(status %in% input$status)
else
  test_data

所以你只在输入不是 "All" 时过滤。如果你有一个很长的 dplyr 链并且你不想把它分成几块,你也可以这样做:

if(input$status=="All")
  my_filter=unique(test_data$status)
else
  my_filter = input$status

test_data %>%
  filter(status %in% my_filter) %>%
  ..... %>%
  .....

希望对您有所帮助。

如果您希望根据外部值有条件地应用过滤器,您可以尝试使用语法:

TRUE

table <- reactive({
  test_data %>%
    filter(if(input$status != 'All')  (status == input$status) else TRUE)
}) 

传递 TRUE 作为条件将不会过滤任何行。

{}

替代方法使用 {} 和 returns 未触及的数据集:else ..

table <- reactive({
  test_data %>%
  {if(input$status != 'All') filter(status == input$status) else .}
}) 

%<>%

最后你可以考虑打破管道并使用 magrittr 包中可用的 %<>% 运算符:

if(input$status != 'All') test_data %<>% filter(status == input$status)

怎么样:

table <- reactive({
test_data %>%
filter(status == input$status | input$status == 'All')
})