使用 Shiny 应用程序保存数据时出现问题
Posted
技术标签:
【中文标题】使用 Shiny 应用程序保存数据时出现问题【英文标题】:Problem when using Shiny app to save the data 【发布时间】:2020-04-15 23:49:21 【问题描述】:我有一个闪亮的应用程序,它有很多文本输入。我无法正确保存数据部分,例如,保存到本地驱动器。有什么建议么?
server = function(input, output)
values <- reactiveValues()
#Initial Dataframe
values$df <- data.frame(matrix(ncol=4,nrow=0, dimnames=list(NULL, c("Name", "date","Traning", "certificate"))))
FinalData =observe(
if(input$submit >0)
isolate(values$df <- rbind(values$df,data.frame("name" = input$name,"date" = input$date,
"training" = input$training, "certificate" = input$certificate)))
# saveRDS(values$df)
# saveRDS(FinalData)
)
#display the inputs
output$Combined_table = renderDataTable(values$df)
)
【问题讨论】:
【参考方案1】:试试这个演示:
library(shiny)
.log <- function(...) message(format(Sys.time(), format = "[ %H:%M:%S ]"), " ", ...)
.read <- function(path) if (file.exists(path)) return(readRDS(path))
shinyApp(
ui = fluidPage(
textInput("txt", "Text: "),
actionButton("btn", "Submit"),
tableOutput("tbl")
),
server = function(input, output, session)
.log("hello world")
rv <- reactiveValues()
rv$df <- data.frame(row = 0L, word = "a", stringsAsFactors = FALSE)[0,]
observeEvent(req(input$btn),
.log("submit!")
rv$df <- rbind(rv$df,
data.frame(row = input$btn, word = input$txt,
stringsAsFactors = FALSE))
.log("saveRDS: ", nrow(rv$df))
saveRDS(rv$df, "local.rds")
)
filedata <- reactiveFileReader(1000, session, "local.rds", .read)
output$tbl <- renderTable(filedata())
)
这个应用程序的工程:
我像你一样使用reactiveValues
,以保留内存中的数据。 (注意:从长远来看,向帧迭代添加行是不好的。如果这是少量添加,那么你可能没问题,但它的扩展性很差。每次添加一行时,它都会复制整个帧,内存消耗翻倍。)
我用零行帧预先填充$df
,仅用于格式化。这里没什么特别的。
observe
和 observeEvent
不返回您感兴趣的内容,它应该完全由 side-effect 操作。它确实返回了一些东西,但它真的只对 shiny
内部有意义。
saveRDS
和你一样,没什么花哨的,但它有效。
我添加了shiny::reactiveFileReader
以证明文件正在被保存。当闪亮表显示更新时,这是因为(1)数据已添加到底层框架; (2) 帧被保存到"local.rds"
文件中;然后 (3) reactiveFileReader
注意到底层文件存在并且已经更改,导致 (4) 它调用我的 .read
函数来读取内容并将其作为反应数据返回到 filedata
。这个块一般来说是完全没有必要的,这里只是为了演示。
我为这个reactiveFileReader
创建了一个函数.read
,它对不存在的文件具有弹性。如果文件不存在,它会隐形返回NULL
。可能有更好的方法来做到这一点。
【讨论】:
感谢 r2evans。我想知道将应用程序上传到服务器时它是否会工作,特别是在同一情况下,有些人可能会同时使用该应用程序。一个人的输入是否有可能覆盖其他人的输入?让我试试你的代码。 是的,这是可能的。听起来您需要诸如数据库或 redis(或类似)服务器之类的东西来处理并发访问。如果你一次只说几个,你也许可以使用 sqlite(或duckdb)来代替。 我一直在阅读 Deam Attali 的“Persistent data storage with Shiny”。他提到了一些远程解决方案。我不知道它是否适用于我有权访问的 microsoft SQL 服务器 有了可用的 DBMS,您当然可以让它更适合多个用户。我建议您创建一个包含所有信息的表(可能还有一个Id
字段,其他字段可能有用)和 DBI::dbWriteTable(..., append=TRUE)
该信息。如果您需要定期检查,而不是 reactiveFileReader
,那么 observe(..., invalidateLater(3000);)
将每 3 秒重新触发一次块(根据您的需要调整,意识到它每次都在运行查询,绝对是正确和错误的方法)。
我正在寻找“保证”。欣赏!以上是关于使用 Shiny 应用程序保存数据时出现问题的主要内容,如果未能解决你的问题,请参考以下文章
从命令行守护程序使用 MLMediaLibrary 时出现 XPC 错误