分层数据过滤闪亮

时间:2017-08-02 13:32:11

标签: r shiny

我遇到了闪亮的分层过滤问题。目标是使用具有某种层次结构的列(例如区域 - 国家/地区)加载data.frame,并使用selectInput()来过滤数据。此外,我需要下拉菜单相互依赖,以便第二个菜单仅与第一个选择相关。我的示例应用程序在这里:

library(shiny)
library(dplyr)

data <- data.frame(
  class1 = rep(c("a", "b", "c"), each = 4),
  class2 = c(rep(c("a1", "a2"), each = 2), rep(c("b1", "b2"), each = 2),
             rep(c("c1", "c2"), each = 2)),
  val = 1:12,
  stringsAsFactors = F
)

ui <- fluidPage(sidebarLayout(
  sidebarPanel(
    actionButton('loaddata', 'Load Data'),
    br(), br(),
    selectInput('class1', 'Class 1',
                choices = c('Select class 1' = '')),
    selectInput('class2', 'Class 2',
                choices = c('Select class 1 first' = ''))
  ),
  mainPanel(
    verbatimTextOutput("out"),
    verbatimTextOutput("counter")
  )
))

server <- function(input, output, session) {
  counter <- reactiveVal(0)

  data.all <- eventReactive(input$loaddata, {
    data
  })

  class1 <- reactive({
    if (input$class1 == '_All_') return('')
    else return(input$class1)
  })

  class2 <- reactive({
    if (input$class2 == '_All_') return('')
    else return(input$class2)
  })

  observe({
    class1 <- c('_All_', data.all()$class1)
    updateSelectInput(session, 'class1', choices = class1)
  })

  observe({
    if (class1() == '') {
      class2 <- c('Select class 1 first' = "")
    } else {
      class2 <- data.all() %>%
        filter(grepl(class1(), class1, fixed = T)) %>%
        .$class2 %>% c('_All_', .)
    }

    updateSelectInput(session, 'class2', choices = class2)
  })

  data.filter <- reactive({
    isolate(counter(counter() + 1))

    data.all() %>%
      filter(grepl(class1(), class1, fixed = T),
             grepl(class2(), class2, fixed = T))
  })

  output$out <- renderPrint({ data.filter() })
  output$counter <- renderPrint({ counter() })
}

shinyApp(ui, server)

注意:如果选择了class1()选项,class2_All_被动反应将返回空字符串。然后可以使用dplyr::filter

问题是我遇到了不必要的执行(我在示例应用程序中包含了一个计数器)。例如:

  1. 用户选择input$class1
  2. 这会触发class1()被动
  3. class1()针对第2课触发observe updateSelectInput,并触发data.filter()被动
  4. 第2课的更新selectInput更改input$class2并触发class2()被动
  5. class2()被动触发器data.filter()再次
  6. 将第1课的selectInput切换回_All_后,类似的内容有效。

    问题是,如果你能看到任何方式,data.filter()被动将“等待”,直到所有被动先决条件都准备好并且只触发一次。

    提前致谢!

1 个答案:

答案 0 :(得分:0)

由于第二个触发因为你有updateSelectInput,你只能用eventReactive将它绑定到第二个类:

 data.filter <- eventReactive(class2(),{
    isolate(counter(counter() + 1))

    data.all() %>%
      filter(grepl(class1(), class1, fixed = T),
             grepl(class2(), class2, fixed = T))
  })