【问题标题】:Use dplyr conditional filter in reactive function in Shiny在 Shiny 的反应函数中使用 dplyr 条件过滤器
【发布时间】:2018-01-30 16:10:09
【问题描述】:

我在 Shiny 应用程序反应函数中使用 dplyr。我在 UI 中有一个交互式小部件,用户可以使用它来选择状态,并且将根据所选状态显示数据。不过,我还想提供显示所有内容的选项,这是我称之为“全部”的状态。

我知道如何在没有 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 在特定条件下不过滤?

谢谢!

【问题讨论】:

    标签: r shiny dplyr reactive magrittr


    【解决方案1】:

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

    TRUE

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

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

    {}

    替代方法使用{} 并返回未触及的数据集:else .

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

    %&lt;&gt;%

    最后,您可以考虑打破管道并使用magrittr 包中提供的%&lt;&gt;% 运算符:

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

    【讨论】:

    • 嗨@Konrad,很好的解决方案!我不知道您通过在 filter 语句中传递单个 TRUE 来过滤所有行。
    • 很好的答案!
    【解决方案2】:

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

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

    因此,您仅在输入不是“全部”时进行过滤。如果你有一个很长的 dplyr 链并且你不想把它分成几块,你也可以这样做:

    if(input$status=="All")
      my_filter=unique(test_data$status)
    else
      my_filter = input$status
    
    test_data %>%
      filter(status %in% my_filter) %>%
      ..... %>%
      .....
    

    希望这会有所帮助。

    【讨论】:

    • 谢谢。您发布的第一个示例需要一个 else 否则它会打印一个带有“全部”选项的空表 - 我已经编辑了您的帖子以反映这一点。我喜欢你发布的第二个例子。
    • @Florian 为什么,也许我遗漏了一些东西,但我认为唯一的挑战是 dplyr 的过滤函数评估为 TRUE 取决于 input$status == "All" 并返回所有行。
    【解决方案3】:

    怎么样:

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

    【讨论】:

      猜你喜欢
      • 2018-10-11
      • 2018-06-21
      • 2021-11-30
      • 1970-01-01
      • 2020-07-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多