简体   繁体   English

将RData文件读入Shiny Application

[英]Reading an RData file into Shiny Application

I am working on a shiny app that will read a few RData files in and show tables with the contents. 我正在开发一个闪亮的应用程序,它将读取一些RData文件并显示包含内容的表。 These files are generated by scripts that eventually turns the data into a data frame. 这些文件由脚本生成,最终将数据转换为数据帧。 They are then saved using the save() function. 然后使用save()函数保存它们。

Within the shiny application I have three files: 在闪亮的应用程序中,我有三个文件:

ui.R, server.R, and global.R ui.R,server.R和global.R

I want the files to be read on an interval so they are updated when the files are updated, thus I am using: 我希望在一段时间内读取文件,以便在文件更新时更新它们,因此我使用:

reactiveFileReader() 

I have followed a few of the instructions I have found online, but I keep getting an error "Error: missing value where TRUE/FALSE is needed". 我已经按照我在网上找到的一些说明进行了操作,但是我一直收到错误“错误:缺少需要TRUE / FALSE的值”。 I have tried to simplify this so I am not using: 我试图简化这个,所以我没有使用:

reactiveFileReader() 

functionality and simply loading the file in the server.R (also tried in the global.R file). 功能,只需在server.R中加载文件(也在global.R文件中尝试过)。 Again, the 再次,

load()

statement is reading in a data frame. 语句正在读取数据框。 I had this working at one point by loading in the file, then assigning the file to a variable and doing an "as.data.table", but that shouldn't matter, this should read in a data frame format just fine. 通过加载文件,然后将文件分配给变量并执行“as.data.table”,我有一点工作,但这应该无关紧要,这应该以数据帧格式读取就好了。 I think this is a scoping issue, but I am not sure. 我认为这是一个范围问题,但我不确定。 Any help? 有帮助吗? My code is at: 我的代码是:

http://pastebin.com/V01Uw0se http://pastebin.com/V01Uw0se

Thanks so much! 非常感谢!

Here is a possible solution inspired by this post http://www.r-bloggers.com/safe-loading-of-rdata-files/ . 这篇文章的灵感源自http://www.r-bloggers.com/safe-loading-of-rdata-files/ The Rdata file is loaded into a new environment which ensures that it will not have unexpected side effect (overwriting existing variables etc). Rdata文件被加载到一个新环境中,以确保它不会产生意外的副作用(覆盖现有的变量等)。 When you click the button, a new random data frame will be generated and then saved to a file. 单击该按钮时,将生成一个新的随机数据框,然后将其保存到文件中。 The reactiveFileReader then read the file into a new environment. 然后,reactiveFileReader将文件读入新环境。 Lastly we access the first item in the new environment (assuming that the Rdata file contains only one variable which is a data frame) and print it to a table. 最后,我们访问新环境中的第一个项目(假设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)

Ok - I figured out how to do what I need to. 好的 - 我想出了如何做我需要的。 For my first issue, I wanted the look and feel of 'renderDataTable', but I wanted to pull in a data frame (renderDataTable / dataTableOutput does not allow this, it must be in a table format). 对于我的第一个问题,我想要'renderDataTable'的外观和感觉,但我想拉入一个数据框(renderDataTable / dataTableOutput不允许这样,它必须是表格式)。 In order to do this, I found a handy usage of ReportingTools (from Bioconductor) and how they do it. 为了做到这一点,我发现了一个方便的ReportingTools(来自Bioconductor)以及它们是如何做到的。 This allows you to use a data frame directly and still have the HTML table with the sorts, search, pagination, etc.. The info can be found here: 这允许您直接使用数据框,并且仍然具有HTML表,包括排序,搜索,分页等。信息可以在这里找到:

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

Now, for my second issue - updating the data and table regularly without restarting the app. 现在,对于我的第二个问题 - 定期更新数据和表而不重新启动应用程序。 This turned out to be simple, it just took me some time to figure it out, being new to Shiny. 事实证明这很简单,只花了我一些时间来弄明白,对Shiny来说是新手。 One thing to point out, to keep this example simple, I used renderTable rather than the solution above with the ReportingTools package. 有一点需要指出,为了保持这个例子的简单,我使用了renderTable而不是上面使用ReportingTools包的解决方案。 I just wanted to keep this example simple. 我只是想让这个例子变得简单。 The first thing I did was wrap all of my server.R code (within the shinyServer() function) in an observe({}). 我做的第一件事是在observe({})中包装我的所有server.R代码(在shinyServer()函数内)。 Then I used invalidateLater() to tell it to refresh every 5 seconds. 然后我使用invalidateLater()告诉它每5秒刷新一次。 Here is the code: 这是代码:

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

shinyServer(function(input, output, session) {

  observe({

    invalidateLater(5000,session)

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

Now, original for the renderTable() portion, I was just calling the object name of the loaded .Rdata file, but I wanted it to be read each time, so I created a function in my global.R file (this could have been in server.R) to load the file. 现在,对于renderTable()部分,我只是调用加载的.Rdata文件的对象名称,但我希望每次都能读取它,所以我在我的global.R文件中创建了一个函数(这可能是在server.R)加载文件。 That code is here: 那段代码在这里:

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

That's it, nothing else goes in the global.R file. 就是这样,global.R文件中没有其他内容。 Your ui.R would be however you have it setup, call tableOutout, dataTableOutput, or whatever your rendering method is in the UI. 然而,您的ui.R将是您设置,调用tableOutout,dataTableOutput或UI中的任何渲染方法。 So, what happens is every 5 seconds the renderTable() code is read every 5 seconds, which in turns invokes the function that actually reads the file. 因此,每5秒读取一次renderTable()代码会发生什么,这反过来会调用实际读取文件的函数。 I tested this by making changes to the data file, and the shiny app updated without any interaction from me. 我通过更改数据文件测试了这一点,并且更新了闪亮的应用程序而没有与我进行任何交互。 Works like a charm. 奇迹般有效。

If this is inelegant or is not efficient, please let me know if it can be improved, this was the most straight-forward way I could figure this out. 如果这不优雅或效率不高,请告诉我是否可以改进,这是我能想到的最直接的方式。 Thanks to everyone for the help and comments! 感谢大家的帮助和评论!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM