我有一个闪亮的应用程序,带有一个滑块输入和一个选择输入。 plotOutput
中的图会根据这些输入值进行更新。我还有一个 actionButton,它允许我使用 ggsave
保存绘图。
MWE 如下:
library(shiny)
library(ggplot2)
# Define UI for application that draws a histogram
ui <- fluidPage(
tabsetPanel(
tabPanel('Test',
sliderInput("bins",
"Number of bins:",
min = 1,
max = 50,
value = 30), # Does nothing for now, will be implemented later
selectInput('inputtest', 'Select val:',
c('A' = 'a',
'B' = 'b',
'C' = 'c')),
plotOutput("distPlot"),
actionButton('testbtn', 'Test me')
)
)
)
server <- function(input, output) {
output$distPlot <- renderPlot({
if(input$inputtest=='a') {
pltitle <- 'Title A'
} else if(input$inputtest=='b') {
pltitle <- 'Title B'
} else {
pltitle <- 'No more!'
}
plt <- qplot(eruptions, waiting, data=faithful) + ggtitle(pltitle)
print(plt)
observeEvent(input$testbtn, {
print(paste('Saving plot', pltitle))
#ggsave(paste0('Plot-', input$inputtest, '.png'), plt)
})
observeEvent(input$inputtest, {
print(paste('Changed input to', input$inputtest, '| input button was activated', input$testbtn, 'times'))
})
})
}
shinyApp(ui = ui, server = server)
我面临的问题是,每次更新选择输入的值时,observeEvent
中的操作都会重复我对此输入所做更改的次数。
在应用程序启动时,它会在控制台中打印以下消息:
[1] "Changed input to a | input button was activated 0 times"
然后我将选择输入更改为“B”,它显示:
[1] "Changed input to b | input button was activated 0 times"
[1] "Changed input to b | input button was activated 0 times"
然后我把它改回“A”,控制台打印:
[1] "Changed input to a | input button was activated 0 times"
[1] "Changed input to a | input button was activated 0 times"
[1] "Changed input to a | input button was activated 0 times"
如果我现在点击操作按钮导出绘图,控制台会打印:
[1] "Saving plot Title B"
[1] "Saving plot Title A"
[1] "Saving plot Title A"
它想先保存情节 B,然后两次情节 A...
单击操作按钮后,每次更改选择值时,都会在重复的 print
指令中间保存另一个图(例如,如果我将选择设置为 C):
[1] "Changed input to c | input button was activated 1 times"
[1] "Changed input to c | input button was activated 1 times"
[1] "Changed input to c | input button was activated 1 times"
[1] "Saving plot No more!"
[1] "Changed input to c | input button was activated 1 times"
在我的完整应用程序中,滑块输入在绘图显示上有一个动作并保存了这样的绘图,它使用默认滑块值保存。
这种行为不仅会增加应用的处理时间,还会保存不需要的图,有时还会删除我通过应用调整过的图。
这是 Shiny 的正常行为吗,我误解了什么?如果是,我怎样才能获得预期的行为(一次更改 = 一次更新;没有不需要的绘图保存)?
如果不是,我想我应该在 Shiny repo 上提交问题。
谢谢。
答案 0 :(得分:1)
Y>你不想让你的观察者留在渲染函数中,因为这会导致每次调用渲染函数时都会对观察者进行新的初始化。我还将渲染函数中的代码拆分为两个响应式语句,以便我们可以在不同的位置访问。
server <- function(input, output) {
pltitle <- reactive({
if(input$inputtest=='a') {
'Title A'
} else if(input$inputtest=='b') {
'Title B'
} else {
'No more!'
}
})
plt <- reactive({
qplot(eruptions, waiting, data=faithful) + ggtitle(pltitle())
})
output$distPlot <- renderPlot({
print(plt())
})
observeEvent(input$testbtn, {
print(paste('Saving plot', pltitle()))
#ggsave(paste0('Plot-', input$inputtest, '.png'), plt)
})
observeEvent(input$inputtest, {
print(paste('Changed input to', input$inputtest, '| input button was activated', input$testbtn, 'times'))
})
}
shinyApp(ui = ui, server = server)
ui 功能可以不做。