R shiny中的多个动态过滤器更新
我希望能够在shiny中拥有UI输入,这些输入根据用户以前的选择进行自我更新。因此,在下面的示例中,预期的行为将是用户从R shiny中的多个动态过滤器更新,r,shiny,reactive,R,Shiny,Reactive,我希望能够在shiny中拥有UI输入,这些输入根据用户以前的选择进行自我更新。因此,在下面的示例中,预期的行为将是用户从cyl、vs或carb中进行选择,然后 过滤用于创建绘图的数据集mtcars,即用户根据过滤条件和 更新其他过滤器中的剩余输入选项,以便与基于已就位过滤器的剩余选项相对应 以下是我尝试过的: library(shiny) library(dplyr) library(plotly) data("mtcars") # create ui ui <-
cyl
、vs
或carb
中进行选择,然后
mtcars
,即用户根据过滤条件和library(shiny)
library(dplyr)
library(plotly)
data("mtcars")
# create ui
ui <- fluidPage(
fluidRow(
box(
title = "Filter",
uiOutput(outputId = "cyl_dynamic_input"),
uiOutput(outputId = "vs_dynamic_input"),
uiOutput(outputId = "carb_dynamic_input")
),
box(
title = "Plot of mtcars",
plotlyOutput("carplot")
)
),
)
# create server
server <- function(input, output, session) {
# create reactive filters of the mtcars table
mtcars.reactive <-
reactive({
mtcars %>%
filter(mpg %in% input$cyl_input_rendered &
vs %in% input$vs_input_rendered &
carb %in% input$carb_input_rendered
)})
## create rendered inputs
# for cyl
output$cyl_dynamic_input <- renderUI({
pickerInput(inputId = "cyl_input_rendered",
label = "CYL",
choices = unique(mtcars$cyl),
multiple = T,
selected = mtcars.reactive()$cyl,
options = list(
`actions-box` = TRUE,
`selected-text-format`= "count",
`count-selected-text` = "{0} out of {1} cyl selected"
))
})
# for vs
output$vs_dynamic_input <- renderUI({
pickerInput(inputId = "vs_input_rendered",
label = "VS",
choices = unique(mtcars$vs),
multiple = T,
selected = mtcars.reactive()$vs,
options = list(
`actions-box` = TRUE,
`selected-text-format`= "count",
`count-selected-text` = "{0} out of {1} vs selected"
))
})
# for carb
output$carb_dynamic_input <- renderUI({
pickerInput(inputId = "carb_input_rendered",
label = "CARB",
choices = unique(mtcars$carb),
multiple = T,
selected = mtcars.reactive()$carb,
options = list(
`actions-box` = TRUE,
`selected-text-format`= "count",
`count-selected-text` = "{0} out of {1} carb selected"
))
})
## create the plot output
# Start Barplot Emissionen here
output$carplot<-
renderPlotly({
# create plot
plot<-ggplot(mtcars.reactive(), aes(wt, mpg))+
geom_point()
# convert to plotly
ggplotly(plot)
})
}
shinyApp(ui, server)
库(闪亮)
图书馆(dplyr)
图书馆(绘本)
数据(“mtcars”)
#创建用户界面
ui以下操作不需要层次结构,而是在observeEvent
语句中使用pickerInput
和条件语句。它一开始看起来很复杂,但做了它应该做的事情
library(shiny)
library(dplyr)
library(plotly)
data("mtcars")
# create ui
ui <- fluidPage(fluidRow(
box(
title = "Filter",
pickerInput(
inputId = "cyl_pickerinput",
label = "CYL",
choices = levels(as.factor(mtcars$cyl)),
multiple = T,
selected = levels(as.factor(mtcars$cyl)),
options = list(
`live-search` = TRUE,
#`actions-box` = TRUE,
`selected-text-format` = "count",
`count-selected-text` = "{0} out of {1} cyl selected"
)
),
pickerInput(
inputId = "vs_pickerinput",
label = "VS",
choices = levels(as.factor(mtcars$vs)),
multiple = T,
selected = levels(as.factor(mtcars$vs)),
options = list(
`live-search` = TRUE,
#`actions-box` = TRUE,
`selected-text-format` = "count",
`count-selected-text` = "{0} out of {1} vs selected"
)
),
pickerInput(
inputId = "carb_pickerinput",
label = "CARB",
choices = levels(as.factor(mtcars$carb)),
multiple = T,
selected = levels(as.factor(mtcars$carb)),
options = list(
`live-search` = TRUE,
#`actions-box` = TRUE,
`selected-text-format` = "count",
`count-selected-text` = "{0} out of {1} carb selected"
)
),
),
box(title = "Plot of mtcars",
plotlyOutput("carplot"))
),)
# create server
server <- function(input, output, session) {
#(1) Create PickerInput Updates
observeEvent(
# define pickerinputs to be observed
c(
input$vs_pickerinput,
input$carb_pickerinput,
input$cyl_pickerinput
),
{
## filter the data based on the pickerinputs
# include an ifelse condition first to check wheter at least one value is choosen in all of the filters.
mtcars2 <-
if (!is.null(input$cyl_pickerinput) &
!is.null(input$vs_pickerinput) &
!is.null(input$carb_pickerinput)) {
mtcars %>%
filter(cyl %in% input$cyl_pickerinput) %>% # filters
filter(vs %in% input$vs_pickerinput) %>%
filter(carb %in% input$carb_pickerinput)
}
else{
mtcars
}
## update PickerInput based on a condition that requires the user to choose at least one input, else reset all filters
# for cyl
if (!is.null(input$cyl_pickerinput)) {
updatePickerInput(
session,
"cyl_pickerinput",
choices = levels(factor(mtcars$cyl)),
selected = unique(mtcars2$cyl))
} else{
}
# for carb
if (!is.null(input$carb_pickerinput)) {
updatePickerInput(
session,
"carb_pickerinput",
choices = levels(factor(mtcars$carb)),
selected = unique(mtcars2$carb)
)
}
# for vs
if (!is.null(input$vs_pickerinput)) {
updatePickerInput(
session,
"vs_pickerinput",
choices = levels(factor(mtcars$vs)),
selected = unique(mtcars2$vs)
)
}
},
ignoreInit = TRUE,
ignoreNULL = F
)
# (2) Create reactive object with filtered data
# update mtcars table based on filters
mtcars.reactive <-
reactive({
if (!is.null(input$vs_pickerinput))
# one condition should be enough.
{
mtcars %>% # filters
filter(
cyl %in% input$cyl_pickerinput &
vs %in% input$vs_pickerinput &
carb %in% input$carb_pickerinput
)
} else
{
mtcars
}
})
# (3) create the plot output
output$carplot <-
renderPlotly({
# create plot
plot <- ggplot(mtcars.reactive()) +
geom_point(aes(wt, mpg, color = factor(vs)))
# convert to plotly
ggplotly(plot)
})
}
shinyApp(ui, server)
库(闪亮)
图书馆(dplyr)
图书馆(绘本)
数据(“mtcars”)
#创建用户界面
ui%
过滤器(输入$carb\u pickerinput中的carb%
}
否则{
地铁车辆
}
##根据要求用户至少选择一个输入的条件更新PickerInput,否则重置所有筛选器
#共青团
如果(!为.null(输入$cyl\u pickerinput)){
更新输入(
一场
“共青团皮克林普特”,
选项=级别(系数(mtcars$cyl)),
选定=唯一(mtcars2$cyl))
}否则{
}
#碳水化合物
如果(!is.null(输入$carb\u pickerinput)){
更新输入(
一场
“carb_pickerinput”,
选项=水平(系数(mtcars$carb)),
选定=唯一(mtcars2$carb)
)
}
#对于vs
如果(!is.null(输入$vs_pickerinput)){
更新输入(
一场
“vs_pickerinput”,
选项=水平(系数(mtcars$vs)),
选定=唯一(mtcars2$vs)
)
}
},
ignoreInit=TRUE,
ignoreNULL=F
)
#(2)使用过滤后的数据创建反应对象
#基于过滤器更新mtcars表
mtcars.reactive%#过滤器
滤器(
%input$cyl\u pickerinput中的%cyl%&
输入$vs\u pickerinput中的%vs%&
carb%在%input$carb\u pickerinput中
)
}否则
{
地铁车辆
}
})
#(3)创建打印输出
输出$carplot要根据另一个的选定值更改一个拾取输入的选定值,您需要在响应定义的拾取输入更改的反应(observeEvent
)内使用updatePickerInput
。无需使用uiOutput
/renderUI
。您还必须确保逻辑不会互锁:如果用户取消选择所有内容,则可能无法返回,因为mtcars.reactive()将为空,因此所有唯一(…)选择的可能性也将变为空,谢谢你们的评论。我可以算出第一个答案,然后再提供答案。然而,@Waldi关于互锁的第二条评论并非如此。您建议如何解决mtcars为空而取消全部选择的问题?您可能需要在pickerInputs之间保持层次结构:第一个完全空闲,第二个取决于第一个,第三个取决于第一个和第二个。不像你最初希望的那样开放,但更容易理解/处理