【问题标题】:reactiveFileReader in Shiny for .RDataShiny for .RData 中的 reactiveFileReader
【发布时间】:2018-12-03 06:59:33
【问题描述】:

我当前在闪亮应用程序中的工作流程是定期将 R 脚本作为 cron 作业运行,以从多个数据库中提取各种表以及从某些 API 下载数据。然后将它们作为 .Rdata 文件保存在名为 data 的文件夹中。

在我的global.R 文件中,我使用load("data/workingdata.Rdata") 加载数据。这会导致所有数据帧(大约 30 个)加载到环境中。我知道我可以使用reactiveFileReader() 函数来刷新数据,但显然它必须在 server.R 文件中使用,因为与该函数有关联的会话。另外,我不确定load 是否在reactiveFileReader() 中被接受为readFunc。对于这里的场景,最好的策略应该是什么?

【问题讨论】:

  • 你看到this answer了吗?也许reactivePollinvalidateLater 在这里也可能很有趣。
  • @SeGa 谢谢,这正是我用来找出某种解决方案的帖子!

标签: r shiny


【解决方案1】:

此示例使用reactiveVal 对象与observeinvalidateLater。数据每 2 秒加载到新环境并分配给 reactiveVal。

library(shiny)

ui <- fluidPage(
  actionButton("generate", "Click to generate an Rdata file"),
  tableOutput("table")
)

server <- shinyServer(function(input, output, session) {

  ## Use reactiveVal with observe/invalidateLater to load Rdata
  data <- reactiveVal(value = NULL)
  observe({
    invalidateLater(2000, session)
    n <- new.env()
    print("load data")
    env <- load("workingdata.Rdata", envir = n)
    data(n[[names(n)]])
  })


  ## Click the button to generate a new random data frame and write to file
  observeEvent(input$generate, {
    sample_dataframe <- iris[sample(1:nrow(iris), 10, F),]
    save(sample_dataframe, file="workingdata.Rdata")
    rm(sample_dataframe)
  })

  ## Table output
  output$table <- renderTable({
    req(data())
    data()
  })
})


shinyApp(ui = ui, server = server)

【讨论】:

    【解决方案2】:

    关于您的工作流程的一些想法:

    最后,使用 RData 方法,您将设置另一个与您的数据库/API 并行的数据源。

    处理文件时总会产生一些日常开销(例如,您的 .RData 文件在读取时是否已完成?)。在我看来,这(部分)是 DBMS 的用途——照顾家务。他们中的大多数都有复杂的解决方案,以确保您快速获得查询的内容;那为什么要重新发明轮子呢?

    可以使用 reactivePoll 直接查询数据库的更改,而不是不断创建 .RData 文件并使用 reactiveFileReader() 函数轮询数据(请参阅 this 例如使用 sqlite)。如果您的查询长时间运行(我猜这是您的工作流程的原因),您可以在将来包装它们并异步运行它们(参见post 获得一些灵感)。 或者,许多 DBMS 提供诸如物化视图之类的东西以避免长时间等待(根据假定的用户权限)。

    当然,所有这些都是基于假设,因为我不知道您的生态系统,但根据我的经验,减少接口意味着减少错误来源。

    【讨论】:

    • 感谢您的评论。正如您猜对的那样,从用户体验的角度来看,执行查询需要很长时间(在某些情况下需要 7 到 8 分钟)。我已经在使用异步编程,但是对于查询来说,这么长的时间仍然是不可接受的。因此,.Rdata 方法。投票每 4 小时一次。
    • 如果您继续将load() 用作readFunc 用于reactiveFileReader(),则应将其包装在tryCatch() 中以获取24/7 可用的应用程序。
    【解决方案3】:

    您可以在 server.R 的顶部使用load("data/workingdata.Rdata")。然后,只要有人开始新的 Shiny 会话,数据就会是最新的。可能的缺点是:

    • 如果在新的 Shiny 会话加载数据的同时写入数据,则可能会出现问题。
    • 如果会话在新数据可用之前和之后打开,则数据将过时。

    我想第一个可能的问题不会出现足以成为问题。第二个可能的问题更有可能发生,但除非你处于非常危急的情况,否则我看不出这是一个足够严重的问题来担心。

    这对你有用吗?

    【讨论】:

    • 感谢您的回答,但不幸的是,这不是一个选项。该应用 24x7 全天候可用(几乎是关键任务),用户不会开始新的会话。
    猜你喜欢
    • 2016-05-25
    • 1970-01-01
    • 1970-01-01
    • 2016-10-30
    • 2016-01-09
    • 2021-08-02
    • 1970-01-01
    • 1970-01-01
    • 2019-03-23
    相关资源
    最近更新 更多