【发布时间】:2017-08-02 13:32:11
【问题描述】:
我对闪亮的分层过滤有疑问。目标是加载具有某些层次结构(例如区域 - 国家)的列的 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)
注意:如果选择了 _All_ 选项,class1() 和 class2 反应式将返回一个空字符串。那么就可以使用dplyr::filter了。
问题是我遇到了不必要的执行(我在示例应用程序中包含了一个计数器)。示例:
- 用户选择
input$class1 - 这会触发
class1()反应式 -
class1()触发observe和updateSelectInput用于第 2 类,还触发data.filter()反应 - 2 类的更新
selectInput更改input$class2并触发class2()反应 -
class2()响应式再次触发data.filter()
将 1 类的 selectInput 切换回 _All_ 后,类似的事情也有效。
问题是您是否可以看到这可能以data.filter() 反应式将“等待”直到所有反应式先决条件都准备好并且仅触发一次的方式编写。
提前致谢!
【问题讨论】: