【问题标题】:Shinyapp.io to read a local file that update its content every 5 minutesShinyapp.io 读取本地文件,每 5 分钟更新一次其内容
【发布时间】:2020-07-09 00:52:03
【问题描述】:

我的闪亮应用每 5 分钟从我桌面上的本地文件中读取一次内容,因为该文件的内容也每 5 分钟更新一次。而我闪亮的应用程序基本上是读入新内容并将数据附加到现有数据帧并每 5 分钟绘制一次新内容。

问题:最终,我想在网上主持这个。如果我在shinyapps.io 上托管它,我是否仍然能够读取桌面上每 5 分钟更新一次的本地文件?如果没有,我该怎么办?

【问题讨论】:

  • Shinyapps.io 是一个相当静态的设置(不太适合持续数据更新,afaik)。考虑到与存储服务(Dropbox、Google Drive、GCP 存储桶等)接口的 R 包的丰富性,我倾向于从外部资源中获取数据。如果这是您可能考虑的路径,很高兴写一个更全面的答案。
  • Shinyapp 是我在谷歌上搜索出来的第一件事。我全神贯注于所有意见。事实上,如果你不介意为这些类型的任务写一个全面的答案,那就太好了。这将对有类似问题的人有所帮助。
  • 管道工可能会有所帮助。
  • @Chris,这是一个很好的观点,尤其是当需要 R 或 Shiny 仪表板之外的数据时。在我的答案中添加了plumbersn-p。

标签: r shiny shinyapps


【解决方案1】:

我没有在 shinyapps.io 上进行闪亮部署的丰富经验 但我会尽量保持这一点。主要限制在于无法安排 CRON 作业从您的 机器按计划进行。因此,我会考虑以下几点:

  • 使用 CRON 作业每 5 分钟将数据推送到存储提供商(将以 Dropbox 为例)
  • 在 Shiny 仪表板中获取数据。

您可以在下面找到几个关于 Dropbox 和 Google Drive 的示例,但您可以轻松地将几乎相同的概念应用于 AWS 和 GCP(尽管您必须摆弄传递秘密或加密您的身份验证令牌)。

Dropbox 示例

rdrop2 提供了一个易于使用的 Dropbox API 包装器。您可以在下面找到一个 关于如何从帐户中推送和检索文本文件的简单示例(来自rdrop2 自述文件)。

library(rdrop2)

# Authenticate and save token for later use2
token <- drop_auth()
saveRDS(token, "~/dropbox_token.rds")

# Create a folder
drop_create('upload_test')
# You can also create a public folder if data is not sensitive
# drop_create('public/upload_test')

# Upload the file in the freshly created folder
drop_upload("~/mtcars.csv", path = "upload_test")

## Retrieveing your file is as simple as
drop_download("upload_test/mtcars.csv", local_path = "~/new_file.csv")

在 Shiny 中实现它

在 Shiny 中应用上述示例的最简洁方法是将数据采集 在 global.R 文件中,该文件将在运行之前导入到您的 Shiny 应用程序中:
global.R:

library(rdrop2)

# Authenticate and save token for later use2
token <- drop_auth(rdstoken = "dropbox_token.rds")

# Retrieveing your file is as simple as
drop_download("upload_test/mtcars.csv", local_path = "data.csv",
              overwrite = TRUE)
drop_df <- read.csv("data.csv", sep = ",")

print("Downloaded and imported data!")

您的app.R 文件将如下所示:

library(shiny)
source("global.R")

ui <- fluidPage(

    # Application title
    titlePanel("Pulling data from Dropbox"),

    mainPanel(
       tableOutput("df_output")
    )
)

server <- function(input, output) {

    output$df_output <- renderTable({
        drop_df
    })
}

shinyApp(ui = ui, server = server)

部署到 shinyapps

然后您可以像往常一样部署您的应用程序(包括身份验证令牌)。

调度数据上传

由于您的数据在本地计算机上每 5 分钟刷新一次,因此需要它 有一个具有该节奏的上传时间表。在这里,我将使用 cronR 包,但是 在 Linux 上使用 crontab 就可以了。

library(cronR)

cron_add(source("data_upload.R"), frequency = "*/5 * * * *", 
         description = "Push data to Dropbox")

plumberapi

正如@Chris 所提到的,调用 API 可能是一种选择,尤其是在需要 R 脚本和 Shiny 仪表板之外的数据时。您可以在下面找到一个短端点,可以调用它来检索 csv 格式的数据。 Shinyapps.io 不支持托管plumber api,因此您必须将其托管在您最喜欢的云提供商上。

library(plumber)
library(rdrop2)

#* @apiTitle Plumber Example API

#* Echo dropbox .csv file
#* @get /get-data
function(req, res) {
  auth_token <- drop_auth(rdstoken = "token.rds")

  drop_download('upload_test/mtcars.csv', dtoken = auth_token,
                local_path = "mtcars.csv", overwrite = TRUE)

  include_file("mtcars.csv", res, 'text/csv')
}

构建和启动服务:

r <- plumb("plumber.R")  
r$run()

【讨论】:

  • 感谢上面的精彩回答。不过我有一个问题:当数据每 5 分钟更新一次并上传到 Dropbox 时,shiny 如何知道 Dropbox 文件内容已被修改并且需要再次重新下载文件,因为 global.R 只执行一次在闪亮的应用程序中。如果我错了,请纠正我。
  • 不用担心,很乐意为您提供帮助。好问题,恐怕仪表板根本不知道这一点(正如您正确发现的那样,没有 webhook 或 ping 可以让仪表板知道新数据已到达),因此将在下一页刷新时可用。我天真地假设数据不需要在 用户实际使用仪表板时更新(我的错)。可以通过 invalidateLater 强制仪表板每 5 分钟轮询一次数据。
猜你喜欢
  • 2020-06-23
  • 1970-01-01
  • 1970-01-01
  • 2014-03-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多