问题描述
我每天都会通过cron作业为我闪亮的应用程序更新我的RData文件。但是,闪亮的应用程序在大多数情况下不会拾取更新,并且会一直显示旧RData文件中的旧数据。
这里是最小的可重现示例。当从我的桌面执行data_processing.R时,它工作正常。然而,当它在Rshiny服务器上完成时,Shiny应用程序不会读取更新的日期和时间戳。
data_processing.R
rm(list=ls())
df <- iris
data_update_date_time <- Sys.time()
save.image("working_dataset.RData", compress = TRUE)
server.R
load("working_dataset.RData")
function(input, output, session) {
# Combine the selected variables into a new data frame
selectedData <- reactive({
df[, c(input$xcol, input$ycol)]
})
clusters <- reactive({
kmeans(selectedData(), input$clusters)
})
output$plot1 <- renderPlot({
palette(c("#E41A1C", "#377EB8", "#4DAF4A", "#984EA3",
"#FF7F00", "#FFFF33", "#A65628", "#F781BF", "#999999"))
par(mar = c(5.1, 4.1, 0, 1))
plot(selectedData(),
col = clusters()$cluster,
pch = 20, cex = 3)
points(clusters()$centers, pch = 4, cex = 4, lwd = 4)
})
## Data update date and time stamp
output$update_date_time <- renderPrint(data_update_date_time)
}
ui.R
pageWithSidebar(
headerPanel('Iris k-means clustering'),
sidebarPanel(
selectInput('xcol', 'X Variable', names(iris)),
selectInput('ycol', 'Y Variable', names(iris),
selected=names(iris)[[2]]),
numericInput('clusters', 'Cluster count', 3,
min = 1, max = 9),
br(),
h4("Date update date time"),
textOutput("update_date_time")
),
mainPanel(
plotOutput('plot1')
)
)
感谢您百忙之中抽出时间。
推荐答案
编辑
在shiny
包中实际上有一个名为reactiveFileReader
的函数,它执行您正在寻找的操作:定期检查文件"上次修改"的时间或大小是否发生了变化,并相应地重新读取。但是,此函数只能在server
上下文中使用,因此每个连接到您的应用的用户将至少读取一次该文件。我答案中的选项3和4没有这些低效率。
此处的原始答案
首先也是最重要的一点是,SHILY无法跟踪文件更改AFAIK。无论何时,您的实现都会重新加载.RData
文件shiny-server
通过bash或 重新启动- 重新加载全局变量,因为应用程序在某个时候变得空闲。
无法判断第二个条件何时满足。因此,我主张使用以下四个选项之一。从Easy到排序,您最好了解自己的闪亮!。
选项1:将LOAD语句放入服务器
这里,每当新用户连接到应用程序时,都会重新加载图像。但是,如果您的.RData
文件很大,这可能会减慢您的应用程序速度。如果速度不是问题,我会选择这个解决方案,因为它既简单又干净。
# server.R
function(input, output, session) {
load("working_dataset.RData")
...
}
每当用户刷新页面时也将重新读取数据()
选项2:只要您想重新导入数据,就重新启动SHINY-SERVER
(另请参阅@shosacos Answer)。这将强制重新加载.Rdata
文件。
$ sudo systemctl restart shiny-server
同样,这可能会减慢您的生产过程,具体取决于应用程序的复杂性。此方法的一个优点是,如果将数据加载到global.R
中,还可以使用导入的数据构建UI。(我假定您没有提供您提供的代码)。选项3:根据"上次修改时间"导入
这里的想法是在用户连接到应用程序时检查.RData
是否已更改。为此,您必须使用包含上次导入版本的时间戳的"全局"变量。以下代码未经测试,但应该可以让您了解如何实现此功能。
# server.R
last_importet_timestamp <- reactiveVal("")
function(input,output,session){
current_timestamp <- file.info(rdata_path)$mtime
if(last_importet_timestamp() != current_timestamp){
# use parent.frame(2) to make data available in other sessions
load(rdata_path, envir = parent.fame(2))
# update last_importet_timestamp
last_importet_timestamp(current_timestamp)
}
...
}
速度方面,这应该比前两个版本更高效。每个时间戳导入数据的次数永远不会超过一次(除非重新启动SHINY服务器或变为空闲)。选项4:"反应性导入"
基本上与选项3相同,但将每隔50ms检查一次文件的更改。以下是此方法的完整工作示例。请注意,除非检测到"上次修改"中的更改,否则不会加载数据,因此产生的开销不会太差。library(shiny)
globalVars <- reactiveValues()
rdata_path = "working_dataset.RData"
server <- function(input, output, session){
observe({
text = input$text_in
save(text = text, file = rdata_path, compress = TRUE)
})
observe({
invalidateLater(50, session)
req(file.exists(rdata_path))
modified <- file.info(rdata_path)$mtime
imported <- isolate(globalVars$last_imported)
if(!identical(imported, modified)){
tmpenv <- new.env()
load(rdata_path, envir = tmpenv)
globalVars$workspace <- tmpenv
globalVars$last_imported <- modified
}
})
output$text_out <- renderText({
globalVars$workspace$text
})
}
ui <- fluidPage(
textInput("text_in", "enter some text to save in Rdata", "default text"),
textOutput("text_out")
)
shinyApp(ui, server)
如果您觉得globalVars$workspace$text
使用不方便,可以使用with
直接访问globalVars$workspace
的内容。
output$text_out <- renderText({
with(globalVars$workspace, {
paste(text, "suffix")
})
})
这篇关于闪亮的应用程序不反映更新RData文件中的更改的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!