【发布时间】:2017-09-15 22:45:08
【问题描述】:
更新:将示例更改为(希望)不那么抽象的示例
我有一个使用 mtcars 数据集的带有两个选项卡的闪亮应用程序。 “Displacement”包含一个散点图,显示 disp 与 mpg,“horsepower”包含一个散点图,显示 hp 与 mpg。两个选项卡都包含一个复选框组输入,允许用户根据气缸数过滤结果。 “生成”按钮会生成图形,这样它就不会在输入更改后立即更改。
每个选项卡都有两个附加按钮。 “比较”是一个切换按钮,它将一个选项卡的复选框输入中的值复制到另一个选项卡的输入并生成结果图,因此您可以轻松比较两个选项卡如何查找相同的输入。 “恢复默认值”将复选框输入重置为其初始值。
这两个按钮的工作方式相同。每个按钮都有自己的观察者,一旦按下按钮,就会触发更新功能。此函数首先更新输入,然后通过更新为此目的创建的反应值生成图,然后切换到包含该图的选项卡。
但是,只有“比较”按钮才能正常工作,只需单击一下即可更新输入并生成图表。另一方面,恢复默认按钮仅更新输入。您还需要按两次才能更新绘图。
我尝试将“恢复默认值”按钮从一个选项卡移动到另一个选项卡,然后它确实在第一次单击时更新绘图,因此行为会根据受影响的绘图是否在与按钮相同的选项卡(下面提供了应用程序,因此您可以自己尝试)。我对这种行为感到困惑,因为将按钮链接到更新函数的 observeEvent() 函数的编码相同。按钮位于哪个选项卡中并不重要。
谁能解释造成这种情况的原因以及我应该更改什么以使两个按钮在一次单击中更新复选框输入和绘图输出?
library(shiny)
library(ggplot2)
ui <- fluidPage(
tabsetPanel(id="App",
tabPanel(
"displacement",
checkboxGroupInput("cyl1", "Number of cylinders", choices=c("4","6","8"), selected="4"),
actionButton("genDisp", "Generate"),
actionButton("switchToHp", "Compare"),
actionButton("resDefDisp", "Restore Default"),
plotOutput("disp")
),
tabPanel(
"horsepower",
checkboxGroupInput("cyl2", "Number of cylinders", choices=c("4","6","8"), selected="8"),
actionButton("genHp", "Generate"),
actionButton("switchToDisp", "Compare"),
actionButton("resDefHp", "Restore Default"),
plotOutput("hp")
)
)
)
server <- function(input, output, session){
# reactive values used to trigger plot generation
generateDisp <- reactiveVal(0)
generateHp <- reactiveVal(0)
# "Generate" Buttons
observeEvent({
input$genDisp
},
{
generateDisp(generateDisp()+1)
})
observeEvent({
input$genHp
},
{
generateHp(generateHp()+1)
})
# "Compare"/"Restore Defaults" buttons
observeEvent({
input$switchToHp
},{
updateHp(cyl=input$cyl1)
})
observeEvent({
input$resDefDisp
},{
updateDisp(cyl="4")
})
observeEvent({
input$switchToDisp
},{
updateDisp(cyl=input$cyl2)
})
observeEvent({
input$resDefHp
},{
updateHp(cyl="8")
})
# Functions updating graphs
updateDisp <- function(cyl=NULL)
{
updateCheckboxGroupInput(session, "cyl1", "Number of cylinders", selected = cyl)
generateDisp(generateDisp()+1)
updateTabsetPanel(session, "App", selected = "displacement")
}
updateHp <- function(cyl=NULL)
{
updateCheckboxGroupInput(session, "cyl2", "Number of cylinders", selected = cyl)
generateHp(generateHp()+1)
updateTabsetPanel(session, "App", selected = "horsepower")
}
# output plots
output$disp <- renderPlot({
generateDisp()
isolate({
data <- filter(mtcars, cyl %in% input$cyl1) %>%
mutate(cyl=as.factor(cyl))
ggplot(data, aes(x=mpg, y=disp, color=cyl)) +
geom_point()
})
})
output$hp <- renderPlot({
generateHp()
isolate({
data <- filter(mtcars, cyl %in% input$cyl2) %>%
mutate(cyl=as.factor(cyl))
ggplot(data, aes(x=mpg, y=hp, color=cyl)) +
geom_point()
})
})
}
shinyApp(ui, server)
【问题讨论】:
标签: r tabs shiny observers reactive