我每天通过我的闪亮应用程序的cron作业更新我的RData文件。 但是,闪亮的应用程序不会在大多数情况下选择更新并继续显示旧RData文件中的旧数据。
这是最小可重复的例子。从我的桌面执行 data_processing.R 时,它可以正常工作。但是,当它在Rshiny服务器上完成时,闪亮的应用程序不会读取更新的日期和时间戳。
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')
)
)
感谢您抽出宝贵时间。
答案 0 :(得分:7)
reactiveFileReader
包中实际上有一个名为shiny
的函数,可以完全满足您的要求:定期检查文件&#34;最后一次修改&#34;时间或大小相应地改变和重新读取。但是,此功能只能在server
上下文中使用,因此对于连接到您应用的每个用户,该文件至少会被读取一次。我的答案中的选项3和4没有这些低效率。
首先,闪亮没有办法跟踪文件变化AFAIK。您的实现只要
重新加载.RData
文件
shiny-server
通过bash或当满足第二个条件时,没有办法说出来。因此,我主张使用以下四种选项之一。从简单到排序,你最了解你的闪亮!。
此处,只要新用户与应用程序连接,就会重新加载图片。但是,如果您的.RData
文件很大,这可能会降低您的应用速度。如果速度不是问题,我会选择这个解决方案,因为它很容易和干净。
# server.R
function(input, output, session) {
load("working_dataset.RData")
...
}
每当用户刷新页面时,也会重新读取数据( F5 )
(另见@shosacos回答)。这会强制重新加载.Rdata
文件。
$ sudo systemctl restart shiny-server
同样,这可能会降低您的制作流程,具体取决于您的应用的复杂程度。这种方法的一个优点是,如果您在global.R
中加载数据,还可以使用导入的数据来构建ui 。 (我假设你没有给出你给的代码)。
这里的想法是在用户连接到应用时检查.RData
是否已更改。要做到这一点,你将不得不使用&#34;全球&#34;包含上次导入版本的时间戳的变量。以下代码未经测试,但应该让您了解如何实现此功能。
# 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)
}
...
}
速度方面,这应该比前两个版本更有效。每个时间戳永远不会导入数据一次(除非闪亮的服务器重新启动或变为空闲)。
基本上,与选项3相同,但每隔50ms检查一次文件是否有变化。以下是此方法的完整工作示例。请注意,除非上次修改&#34;最后一次更改,否则不会加载数据。被检测到,因此产生的开销也不算太差。
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")
})
})
答案 1 :(得分:1)
如果在处理新的* .RData后重新启动闪亮服务器,它会起作用。我不会把它放进闪亮的服务器,因为那时
1)其变量对UI不可见
2)每个打开应用程序的用户都需要等待RData加载完成。
答案 2 :(得分:0)
该应用由闪亮服务器缓存,除非在与该闪亮应用相关联的.R文件之一中检测到更改,否则它不会更新该应用。 hack是对您的应用程序代码进行微妙的更改(例如,切换库的加载顺序),以提示闪亮的服务器重置缓存,从而包含更新的.RData文件。