【问题标题】:Passing reactive data to global environment将反应数据传递到全局环境
【发布时间】:2019-04-24 05:51:27
【问题描述】:

我想在 RMarkdown 中使用 Shiny 让用户上传数据(xlsx 文件)。
然后我想将所有工作表作为 R 数据帧(无反应性)传递以运行 RMarkdown 文件的其余部分。
我主要想将它们转换成数据帧,这样我也可以使用reticulate 来运行 Python 代码。

这个我试过了,好像不太好用:


library(dplyr)
library(miniUI)
library(shiny)
library(XLConnect)

launch_shiny <- function() {

  ui <- miniPage(
    gadgetTitleBar("Input Data"),
    miniContentPanel(
      fileInput(inputId = "my.file", label = NULL, multiple = FALSE)
    )
  )

  server <- function(input, output, session) {
    wb <- reactive({
      new.file <- input$my.file
      loadWorkbook(
        filename = new.file$datapath,
        create = FALSE,
        password = NULL
      )
    })

    observeEvent(input$done, {
      stopApp(c(wb()))
    })

  }
  runGadget(ui, server)

}

test <- launch_shiny()
df1 <- readWorksheet(object = test, sheet = "sheet1")
df2 <- readWorksheet(object = test, sheet = "sheet2")

它会抛出这个错误:

Error in (function (classes, fdef, mtable)  : 
  unable to find an inherited method for function ‘readWorksheet’ for signature ‘"list", "character"’

我可以使用stopApp(readWorksheet(object = wb(), sheet = "sheet1")) 一次返回一张工作表,但我似乎无法同时返回整个工作簿或多个数据框。

我真的不想在 xlsx 中读取,将每个工作表保存为工作目录中的 csv,然后再次读取这些文件。
有人对如何解决这个问题有好的建议吗?

【问题讨论】:

    标签: r shiny r-markdown


    【解决方案1】:

    fileInput() 的文档中有详细说明:

    数据路径

    包含数据的临时文件的路径 上传。如果用户执行另一次上传,此文件可能会被删除 操作。

    意思是输入变量中给出的datapath是一个临时文件,关闭App后就无法访问了,这也是readWorksheet函数会尝试做的事情。

    因此,您必须阅读服务器中的表格并以某种方式返回数据帧。 我通过定义第二个反应值来做到这一点,该值基本上是通过在wb 中的所有工作表上应用lapply 返回的数据帧列表,在这种情况下test 将是这个数据帧列表。

    可能有其他方法(更有效,或者更适合您的目的)来做到这一点,但这里是:

    library(dplyr)
    library(miniUI)
    library(shiny)
    library(XLConnect)
    
    launch_shiny <- function() {
    
      ui <- miniPage(
        gadgetTitleBar("Input Data"),
        miniContentPanel(
          fileInput(inputId = "my.file", label = NULL, 
                    multiple = FALSE)
        )
      )
    
      server <- function(input, output, session) {
        wb <- reactive({
          new.file <- input$my.file
          loadWorkbook(
            filename = new.file$datapath,
            create = FALSE,
            password = NULL
          )
        })
    
        # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        df_lst <- reactive({
          # read all sheets into a list
          lapply(getSheets(wb()), 
                 function(sheet){
                   readWorksheet(object = wb(), 
                                 sheet = sheet)
                 })
        })
       # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    
        observeEvent(input$done, {
          # get the list of dfs from the app
          stopApp(c(df_lst())) 
        })
    
      }
      runGadget(ui, server)
      }
    
    test <- launch_shiny()
    

    【讨论】:

    • 聪明!我应该考虑返回一个列表,我对数据框太着迷了。太好了,非常感谢!
    • 很高兴为您提供帮助! :)
    猜你喜欢
    • 1970-01-01
    • 2017-09-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-06-25
    • 1970-01-01
    • 1970-01-01
    • 2021-05-29
    相关资源
    最近更新 更多