我有一个小shiny
应用,它使用dateRangeInput
仅绘制数据的子集。
我试图初始化dateRangeInput
(max,min,start,end)的值以匹配数据集的值(默认情况下绘制整个范围)。
一种方法是使用updateDateRangeInput
。它可以工作,但只有在UI上短暂显示的错误之后。 (我也尝试过讨论的解决方案here,here和here,它在用户界面中使用uiOutput
,在服务器端使用renderUI
,但我找到了基本上是同样的问题)。
这是我的(希望最小的)可重现的示例(如果您安装了shiny
,您应该只需复制并粘贴代码即可查看我的意思):
library(shiny)
library(dplyr)
get_data <- function(){
set.seed(1234567)
data.frame(
date = sort(sample(seq(as.Date('2014/01/01'), as.Date('2017/01/01'), by = "day"), 200)),
value = runif(200)
)
}
# Here's my UI
ui <- fluidPage(
dateRangeInput("dateRange", label = "Date range"),
plotOutput(outputId = "thePlot", height = "520px")
)
# And here's my server
server <- function(input, output, clientData, session) {
the_data <- reactive({
# Get the data
my_data <- get_data()
# And update the date range values to match those of the dataset
updateDateRangeInput(
session = session,
inputId = "dateRange",
start = min(my_data$date),
end = max(my_data$date)
)
my_data
})
output$thePlot <- renderPlot({
# I need to subset the data, using the user input (dateRangeInput)
data_subset <- dplyr::filter(the_data(),
date >= input$dateRange[[1]],
date <= input$dateRange[[2]]
)
str(data_subset)
# And plot the subset of data
plot(x = data_subset$date,
y = data_subset$value)
})
}
shinyApp(ui, server)
所以这个应用程序基本上加载了一个我不知道的数据集,因此,我不知道在UI上硬编码它的日期范围。
用户界面只有dateRangeInput
和plotOutput
。服务器端定义了一个用于加载数据的reactive
表达式和一个renderPlot
,它只使用UI上dateRangeInput
给出的范围对数据进行子集化。
请注意,UI上的dateRangeInput
没有定义最大,最小,开始或结束日期(因此,使用默认的NULL值)。那是因为此时我对数值没有任何线索,只有在数据加载的运行时我知道什么是合适的值(整个数据范围)。当然,我可以在UI上设置一些任意值,但它们只是那个可能有效或无效的任意值。
所以我想要做的是让我的应用加载数据并使用适当的值更新dateRangeInput
。我在加载数据后就这样做了。它有效,但在renderPlot
上遇到错误后绊倒了。
在更新renderPlot
值之前会发生dateRangeInput
会发生什么,因此,renderPlot
使用NULL值来对数据进行子集,这会导致错误。此错误会短暂显示给用户。然后,dateRangeInput
值会更新,并且图表会正确呈现。
我检查了流程,updateDateRangeInput
确实在renderPlot
之前执行了。但是,这些值实际上已经更新了。
实际上在updateDateRangeInput
的帮助页面上描述了此行为:
输入更新程序功能向客户端发送消息,告诉它 更改输入对象的设置。收集消息 并在所有观察员(包括产出)完成后发送 运行
因此,即使updateDateRangeInput
在renderPlot
之前执行,它也只会收集仅在renderPlot
完成运行后发送给客户端的消息。
有没有办法强制updateDateRangeInput
立即将消息发送给客户端?
或者如何在执行其他输出之前从服务器端初始化dateRangeInput
的值?
提前致谢,对于这么长的消息感到抱歉(俗话说,我没有时间写一条短信,但我希望这个可重复的例子能够说明我的问题。)< / p>