【发布时间】:2017-08-09 14:05:13
【问题描述】:
我有一个 Shiny 用例,我希望允许用户通过选择列并查看某些摘要统计信息来过滤他们的数据。这个想法是让他们能够快速深入到更细化的组并查看结果。它工作得很好,除非用户在更高级别进行选择,然后所有过滤器和选择都被重置并需要再次选择。我在使这些过滤器持久化并且仅在某些情况下更新时遇到了一些麻烦。
例如,用户想要查看瑞士和德国(第 2 级)工程师(第 1 级)的收入中位数,并按年龄(第 3 级)显示。他们将按每个表上方的selectInput 值进行排序以选择类别,然后选择表中的值以包含“工程师”等变量,如下图所示。
如果他们想查看“试点”如何改变结果,国家过滤器将会消失。我希望那些都留在原地,这就是让我适应的部分。
关于如何解决这个问题的任何想法?本示例代码如下:
服务器:
library(shiny)
library(DT)
library(plyr)
library(dplyr)
# Generate income data
n <- 1000
age <- sample(20:60, n, replace=TRUE)
sex <- sample(c("M", "F"), n, replace=TRUE)
country <- sample(c("US", "CA", "UK", "DE", "CH", "NL"), n, replace=TRUE)
occupation <- sample(c("Engineer", "Doctor", "Retail", "Pilot"), n, replace=TRUE)
income <- sample(20000:120000, n, replace=TRUE)
df <- data.frame(age, sex, country, income, occupation)
categories <- c("None", "age", "sex", "country", "occupation")
shinyServer(function(input, output, session) {
output$selection_1 <- renderUI({
selectInput("selection_1", "Level 1 Selection", selected = "None",
choices = categories)
})
output$selection_2 <- renderUI({
selectInput("selection_2", "Level 2 Selection", selected = "None",
choices = categories)
})
output$selection_3 <- renderUI({
selectInput("selection_3", "Level 3 Selection", selected = "None",
choices = categories)
})
table_1 <- reactive({
validate(
need(input$selection_1 != "None", "Select a variable for aggregation.")
)
ddply(df, input$selection_1, summarize,
Count = length(income),
Med_Income = median(income))
})
output$table_1_agg <- DT::renderDataTable(
table_1(),
rownames = TRUE,
selection = list(selected = "")
)
# Get values to match on subsequent tables
table_1_vals <- reactive({
table_1()[input$table_1_agg_rows_selected, 1]
})
# Filter table 2
table_2 <- reactive({
validate(
need(input$selection_2 != "None", "Select a variable for aggregation.")
)
# Filter selected values from table_1
if(length(table_1_vals())>0){
sel_1_col <- grep(input$selection_1, names(df))
df2 <- df[df[,sel_1_col] %in% table_1_vals(),]
}else{
df2 <- df
}
ddply(df2, input$selection_2, summarize,
Count = length(income),
Med_Income = median(income))
})
output$table_2_agg <- DT::renderDataTable(
table_2(),
rownames = TRUE,
selection = list(selected = "")
)
# Get values to match on subsequent tables
table_2_vals <- reactive({
table_2()[input$table_2_agg_rows_selected, 1]
})
# Filter table 3
table_3 <- reactive({
validate(
need(input$selection_3 != "None", "Select a variable for aggregation.")
)
df3 <- df
# Filter selected values from table_1
if(length(table_1_vals())>0){
sel_1_col <- grep(input$selection_1, names(df))
df3 <- df3[df3[,sel_1_col] %in% table_1_vals(),]
}
if(length(table_2_vals())>0){
sel_2_col <- grep(input$selection_2, names(df))
df3 <- df3[df3[,sel_2_col] %in% table_2_vals(),]
}
ddply(df3, input$selection_3, summarize,
Count = length(income),
Med_Income = median(income))
})
output$table_3_agg <- DT::renderDataTable(
table_3(),
rownames = TRUE,
selection = list(selected = "")
)
})
用户界面:
shinyUI(fluidPage(
fluidRow(
column(6,
uiOutput("selection_1"),
DT::dataTableOutput("table_1_agg")),
column(6,
uiOutput("selection_2"),
DT::dataTableOutput("table_2_agg"))
),
fluidRow(
column(6,
br(),
uiOutput("selection_3"),
DT::dataTableOutput("table_3_agg"))
)
))
谢谢!
【问题讨论】: