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並擺脫生成按鈕。 –