【问题标题】:Reading an RData file into Shiny Application将 RData 文件读入 Shiny 应用程序
【发布时间】:2016-10-30 01:30:02
【问题描述】:

我正在开发一个闪亮的应用程序,它将读取一些 RData 文件并显示包含内容的表格。这些文件由最终将数据转换为数据框的脚本生成。然后使用 save() 函数保存它们。

在闪亮的应用程序中,我有三个文件:

ui.R、server.R 和 global.R

我希望间隔读取文件,以便在更新文件时更新它们,因此我正在使用:

reactiveFileReader() 

我已按照我在网上找到的一些说明进行操作,但我不断收到错误消息“错误:需要 TRUE/FALSE 的地方缺少值”。我试图简化这一点,所以我没有使用:

reactiveFileReader() 

功能,只需将文件加载到 server.R 中(也在 global.R 文件中尝试过)。再次,

load()

语句正在读取数据帧。我通过加载文件,然后将文件分配给一个变量并执行“as.data.table”来完成这项工作,但这没关系,这应该以数据帧格式读取就可以了。我认为这是一个范围界定问题,但我不确定。有什么帮助吗?我的代码在:

http://pastebin.com/V01Uw0se

非常感谢!

【问题讨论】:

  • 当您使用load 读取Rdata 文件时,会将原始数据框名称(与您保存时相同)加载到您的工作区中。
  • 我知道确实会加载到工作区中。我最终使用了 global.R,只是因为最初我无法让它看到变量。如果我只是加载它,当我打电话时
  • 对不起,我的最后一个条目被截断了:我必须通过“变量
  • 常规数据框需要用到tableoutput和rendertable。
  • @warmoverlow 好的,这是有道理的。实际上,我找到了一种获得 renderDataTable 外观/感觉的简洁方法,但是能够使用来自 Bioconductor 的 ReportTools 的数据帧bioconductor.org/packages/release/bioc/html/ReportingTools.html 我的最后一个问题是能够动态更新此表(不一定使用一个按钮,但有一个轮询或更新数据加载和表格渲染的东西。我找到了各种接近的例子,但还没有找到它。任何提示?再次感谢!

标签: r shiny


【解决方案1】:

这是受http://www.r-bloggers.com/safe-loading-of-rdata-files/ 这篇帖子启发的可能解决方案。 Rdata 文件被加载到一个新环境中,以确保它不会产生意外的副作用(覆盖现有变量等)。单击按钮时,将生成一个新的随机数据框,然后将其保存到文件中。然后,reactiveFileReader 将文件读入新环境。最后,我们访问新环境中的第一项(假设 Rdata 文件仅包含一个变量,即数据框)并将其打印到表中。

library(shiny)

# This function, borrowed from http://www.r-bloggers.com/safe-loading-of-rdata-files/, load the Rdata into a new environment to avoid side effects
LoadToEnvironment <- function(RData, env=new.env()) {
  load(RData, env)
  return(env)
}

ui <- shinyUI(fluidPage(

  titlePanel("Example"),

  sidebarLayout(
    sidebarPanel(
      actionButton("generate", "Click to generate an Rdata file")
    ),

    mainPanel(
      tableOutput("table")
    )
  )
))

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

  # Click the button to generate a new random data frame and write to file
  observeEvent(input$generate, {
    sample_dataframe <- data.frame(a=runif(10), b=rnorm(10))
    save(sample_dataframe, file="test.Rdata")
    rm(sample_dataframe)
  })

  output$table <- renderTable({
    # Use a reactiveFileReader to read the file on change, and load the content into a new environment
    env <- reactiveFileReader(1000, session, "test.Rdata", LoadToEnvironment)
    # Access the first item in the new environment, assuming that the Rdata contains only 1 item which is a data frame
    env()[[names(env())[1]]]
  })

})

shinyApp(ui = ui, server = server)

【讨论】:

  • 有趣 - 类似于我刚刚根据其他几个示例的片段得出的结论。 reactiveFileReader 没有看到我需要它做的事情,但是,我构建了一个函数。然后,当我渲染表格时,我为表格分配了函数。然后我将整个事情包装在一个“观察”语句中,并告诉它每 5 秒刷新一次。这正是我想要的。我会发布代码,你可以告诉我这是否有任何不雅之处......
【解决方案2】:

好的 - 我想出了如何做我需要做的事情。对于我的第一个问题,我想要“renderDataTable”的外观和感觉,但我想拉入一个数据框(renderDataTable / dataTableOutput 不允许这样做,它必须是表格格式)。为了做到这一点,我找到了 ReportingTools(来自 Bioconductor)的方便用法以及他们是如何做到的。这允许您直接使用数据框,并且仍然拥有带有排序、搜索、分页等的 HTML 表格。可以在此处找到信息:

https://bioconductor.org/packages/release/bioc/html/ReportingTools.html

现在,关于我的第二个问题 - 定期更新数据和表格,而无需重新启动应用程序。事实证明这很简单,我只是花了一些时间才弄清楚,对 Shiny 来说是新手。需要指出的一点是,为了使这个示例简单,我使用了 renderTable 而不是上面带有 ReportingTools 包的解决方案。我只是想让这个例子简单。我做的第一件事就是将我所有的 server.R 代码(在 shinyServer() 函数中)包装在一个 observe({}) 中。然后我使用 invalidateLater() 告诉它每 5 秒刷新一次。代码如下:

## server.R ##
library(shiny)
library(shinydashboard)
library(DT)

shinyServer(function(input, output, session) {

  observe({

    invalidateLater(5000,session)

    output$PRI1LastPeriodTable <- renderTable({
      prioirtyOneIncidentsLastPeriod <- updateILP()
    })
  })
})

现在,对于 renderTable() 部分,我只是调用加载的 .Rdata 文件的对象名称,但我希望每次都读取它,所以我在我的 global.R 文件中创建了一个函数(这个可能已经在 server.R) 中加载文件。代码在这里:

updateILP <- function() {
  load(file = "W:/Projects/R/Scripts/ITPOD/itpod/data/prioirtyOneIncidentsLastPeriod.RData", envir = .GlobalEnv)
  return(prioirtyOneIncidentsLastPeriod)
}

就是这样,global.R 文件中没有其他内容。您的 ui.R 将是您对其进行设置、调用 tableOutout、dataTableOutput 或您在 UI 中的任何呈现方法。因此,每 5 秒发生的情况是,每 5 秒读取一次 renderTable() 代码,然后调用实际读取文件的函数。我通过对数据文件进行更改来测试这一点,并且闪亮的应用程序在没有任何交互的情况下更新。奇迹般有效。

如果这不优雅或效率不高,请告诉我是否可以改进,这是我能解决的最直接的方法。感谢大家的帮助和cmets!

【讨论】:

  • 底层机制与我的解决方案相同(reactiveFileReader 使用reactivePoll,后者使用invalidateLater)。恭喜您解决了问题。
  • 使用reactiveFileReader 仍然有其优势,因为该函数仅在文件更改时读取文件。因此,这减少了磁盘活动和闪亮的服务器负载。
  • @warmoverflow 嗯,也许我应该重新审视一下 reactiveFileReader。我以为那是它应该做的。我在 global.R 中有这样的内容:“dataUpdate
  • 原因是你忘记了括号。应该是data &lt;- updateData()。像函数一样使用reactive
  • @warmoverflow 啊,你知道,我敢打赌我在某个时候是这样的,但由于其他问题,最终改变了它。我将不得不回去尝试这种方式。这似乎比我现在设置的要优雅得多。我接受了你的回答,因为无论如何它让我找到了最终的解决方案。感谢您的所有帮助!
猜你喜欢
  • 2015-07-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-11-27
  • 1970-01-01
  • 2015-09-02
  • 1970-01-01
相关资源
最近更新 更多