我正在基于很棒的 R Shiny 包构建一个探索性视觉应用程序。该应用程序要做的一件事是读取实值“测量”列并显示这些测量值的箱线图。此外,还有一个可选的selectInput
小部件,允许用户选择group要深入研究的变量。这group变量基本上包含具有分类值的列的名称,例如性别(女性与男性)、国家/地区(美国、加拿大等)。因此,如果从以下选项中选择“性别”group selectInput
,应用程序将显示两个箱线图,一个用于女性,另一个用于男性。
为了让用户能够灵活地关注某些类别(例如仅女性),我想出了checkboxGroupInput
仅在以下情况下显示group变量同时被选择choices
and selected
最初设置为所有类别group多变的。例如,当用户只想查看女性的箱线图时,他/她可以轻松取消选中男性的复选框,并且男性的箱线图被删除,而女性的箱线图保留。
下列的暖流 https://stackoverflow.com/users/4190526/warmoverflow的建议,这是一个可复制的玩具示例
# global setup
library(shiny)
library(ggplot2)
library(dplyr)
set.seed(12345)
dummy_data <- data.frame(
Value = c(rnorm(50), 2 + rnorm(50)),
Gender = c(rep('Female', 50), rep('Male', 50)),
Country = c(rep('US', 50), rep('CA', 50)),
stringsAsFactors = FALSE
)
# ui function
ui <- fluidPage(
sidebarLayout(
sidebarPanel(
selectInput('group', 'Group',
c('Choose'='', setdiff(names(dummy_data), 'Value'))),
uiOutput('group_select')
),
mainPanel(plotOutput('box_plot'))
)
)
# server function
server <- function(input, output) {
# the group level select/unselect widget
output$group_select <- renderUI({
req(input$group)
data <- dummy_data
group_levels <- unique(data[[input$group]])
conditionalPanel(
condition = "input.group != ''",
checkboxGroupInput('group_select', input$group,
choices = group_levels, selected = group_levels)
)
})
# filter the data if group variable is selected
data_to_plot <- reactive({
data <- dummy_data
if(!(is.null(input$group) || input$group == '')) {
data <- data %>%
mutate_(group_ = input$group) %>%
filter(group_ %in% input$group_select)
} else {
data$group_ <- as.factor(rep.int(1, nrow(data)))
}
return(data)
})
# show the boxplot
output$box_plot <- renderPlot({
data <- data_to_plot()
validate(
need(!(is.null(data) || nrow(data) == 0),
'There are no data to plot!')
)
ggplot(data = data, aes(factor(group_), Value)) + geom_boxplot()
})
}
shinyApp(ui = ui, server = server)
嗯,代码可以工作,但是reactive
语句不必要地运行两次,一次当input$group
更新后还有另一个input$group_select
得到更新,因为您可以注意到错误消息“没有要绘制的数据!”当您从选项中选择“性别”时group下拉列表。所以我的问题是:有没有办法保证以下执行顺序:
-
input$group
已更新->
-
input$group_select
已更新 ->
-
reactive
更新后(重新)执行input$group
and input$group_select
我花了几乎一整天的时间寻找解决方案但收效甚微。
- 罗杰戴似乎已经解决了这个问题使用 sendInputMessage 和 receiveMessage 使闪亮的输入对象具有反应性 https://groups.google.com/forum/#!topic/shiny-discuss/udPfQ9o8JVY。但他的方法涉及创建一个 jstree,这对我来说完全是一个陌生的领域,看起来他已经从他的 Github 上删除了该解决方案。
- 另一个可能的线索是使用
observeEvent
此处描述(R闪亮观察运行在加载UI之前,这会导致空参数 https://stackoverflow.com/questions/22845874/r-shiny-observe-running-before-loading-of-ui-and-this-causes-null-parameters)。然而,observeEvent
当您取消选择一个或多个类别时忽略它input$group_select
.
Roger Day 指出,其困难在于输入更新函数通常不是反应性的,因此(根据我的实验和理解)比反应性语句执行得晚。或者,如果有一种方法可以使输入更新功能反应,则可以应用优先级值以所需的方式改变执行顺序。
任何意见都将不胜感激!抱歉描述太长!