我修复了一个错误,但我不明白为什么会发生这种情况。有人能帮忙澄清吗?
我正在构建一个交互式数据浏览器应用程序,每个图都包含在自己的模块中。在我的第一种方法("旧版本不起作用"(下,我首先建立一个查找列表,然后使用它来显示正确的控件和绘图。
但是,在单击地物选择列表中的所有选项之前,不会显示任何绘图。
我通过切换到没有中间查找列表的"有效的新版本"来解决这个问题。但不明白为什么会发生这种事。
下面是可复制的最小示例,很抱歉长度太长。
# required packages
library(shiny)
library(tidyverse)
## ui ----
ui = fluidPage(
sidebarLayout(
sidebarPanel(
uiOutput("plot_controls"),
width=3
),
mainPanel(
selectInput("selected_plot", "Select figure:", choices = c("Histogram", "Scatter")),
plotOutput("plot_plot", height = "700px"),
width=9
)))
## server ----
server = function(input, output, session) {
data(starwars)
### modules ----
fig_histogram = callModule(figure_histogram_plot, "histogram", datafile = starwars)
fig_scatter = callModule(figure_Scatter_Plot, "scatter", datafile = starwars)
module_list = list( fig_histogram, fig_scatter )
### old version that does not work ----
resource.map_text_to_plot = reactive({
map = list("Histogram" = module_list[[1]]$plot(), "Scatter" = module_list[[2]]$plot())
})
output$plot_plot = renderPlot({ resource.map_text_to_plot()[input$selected_plot] })
resource.map_text_to_control = reactive({
map = list("Histogram" = module_list[[1]]$control, "Scatter" = module_list[[2]]$control)
})
output$plot_controls = renderUI({ resource.map_text_to_control()[input$selected_plot] })
### new version that works ----
# output$plot_controls = renderUI({
# for(module in module_list)
# if(module$text == input$selected_plot)
# return(module$control)
# })
#
# output$plot_plot = renderPlot({
# for(module in module_list)
# if(module$text == input$selected_plot)
# return(module$plot())
# })
}
shinyApp(ui = ui, server = server)
图形模块如下:
### histogram - server ----
figure_histogram_plot = function(input, output, session, datafile){
text = "Histogram"
control = sliderInput(session$ns("num_bins"), "Number of bins", min = 5, max = 50, value = 30)
plot = reactive({
p = ggplot(data = datafile) + geom_histogram(aes_string(x = "height"), bins = input$num_bins)
return(p)
})
return(list(text = text, plot = plot, control = control))
}
### scatter - server ----
figure_Scatter_Plot = function(input, output, session, datafile){
text = "Scatter"
control = radioButtons(session$ns("plot_design"), "Plot design", choices = c("points", "lines", "both"))
plot = reactive({
p = ggplot(data = datafile)
if(input$plot_design != "lines")
p = p + geom_point(aes_string( x = "mass", y = "height" ))
if(input$plot_design != "points")
p = p + geom_line(aes_string( x = "mass", y = "height" ))
return(p)
})
return(list(text = text, plot = plot, control = control))
}
所以我认为问题在于何时评估反应性元素。当你使用()
来"调用"一个反应性元素时,它就不再是真正的反应性了。设置列表时,请使用
resource.map_text_to_plot = reactive({
map = list("Histogram" = module_list[[1]]$plot,
"Scatter" = module_list[[2]]$plot)
map
})
设置renderPlot时,使用
output$plot_plot = renderPlot({
resource.map_text_to_plot()[[input$selected_plot]]() })
请注意,我们从列表中删除了()
,并将其放在render函数中。
此外,在绘制第一个绘图之前,您的控件不会被初始化,因此input$plot_design
值可能为NULL,并且您似乎没有在第一次绘图时检查导致问题的原因(您很可能会短暂地看到错误(