gpt4 book ai didi

r - Shiny 应用程序不反射(reflect)更新 RData 文件中的更改

转载 作者:行者123 更新时间:2023-12-01 17:06:44 26 4
gpt4 key购买 nike

我每天通过 cron 作业为我的 Shiny 应用程序更新我的 RData 文件。但是, Shiny 的应用程序大多数时候不会选择更新,并继续显示旧 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)

服务器.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 的函数,它完全可以满足您的需求:定期检查文件“上次修改”时间或大小是否发生变化并相应地重读。但是,此函数只能在服务器上下文中使用,因此对于连接到您的应用的每个用户,该文件至少会被读取一次。我的答案中的选项 3 和 4 没有这些低效问题。

原始答案来自此处

首先,Shiny 没有办法跟踪文件更改 AFAIK。您的实现每当

时都会重新加载 .RData 文件
  1. shiny-server 通过 bash 重新启动
  2. 全局变量会重新加载,因为应用程序在某个时刻变得空闲。

无法判断何时满足第二个条件。因此,我建议使用以下四个选项之一。从简单你最好了解你的 Shiny !排序。

选项 1:将加载语句放入服务器

在这里,每当新用户连接应用程序时,都会重新加载图像。但是,如果您的 .RData 文件很大,这可能会减慢您的应用程序的速度。如果速度不是问题,我会选择这个解决方案,因为它简单且干净。

# server.R
function(input, output, session) {
load("working_dataset.RData")
...
}

每当用户刷新页面(F5)时,数据也会被重新读取

选项 2:每当您想要重新导入数据时重新启动 Shiny 服务器

(另请参阅@shosacos 答案)。这会强制重新加载 .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:导入“reactvely”

基本上与选项 3 相同,但每 50 毫秒检查一次文件是否有更改。这是此方法的完整工作示例。请注意,除非检测到“上次修改”的更改,否则不会加载数据,因此产生的开销并不算太糟糕。

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")
})
})

关于r - Shiny 应用程序不反射(reflect)更新 RData 文件中的更改,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46719268/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com