UPDATE:改变到例如(希望)少一个抽象ř闪亮:observeEvent()的行为不同基于什么选项卡打开
我有光泽的应用程序使用所述数据集mtcars两个标签。 “位移”包含显示disp与mpg的散点图,“马力”包含显示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)
谢谢您的回复。我把我的问题中的例子改为了一个不太抽象的例子。我想要的是让按钮允许用户在选项卡之间“切换”,从一个选项卡复制输入值并将它们粘贴到另一个选项卡,以便他可以轻松比较不同图形的相同输入。我也想要按钮将输入更改为某些预定义的值。这第二种按钮通常位于与情节相同的选项卡中,这是我遇到此问题的原因。 –
@FrankvanDorp如果您添加一个浏览器()语句作为renderPlot的第一行并开始调试您的应用程序。您会注意到恢复默认按钮实际上以某种方式触发renderPlot运行两次。这很奇怪,你可能想尝试不使用reactiveVal。我会尝试使用reactiveValues来查看是否有差异 –
@FrankvanDorp当我在帖子中更新时,它是导致延迟的更新*输入函数。在我看来更自然的是,当用户点击恢复默认按钮时,只需更新selectInput,然后让您的绘图完全依赖selectInput并摆脱生成按钮。 –