Передача реактивных данных в глобальную среду - PullRequest
0 голосов
/ 24 апреля 2019

Я хочу использовать Shiny в RMarkdown для пользователей, чтобы загружать данные (файл 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 в рабочем каталоге, а затем снова читать эти файлы.
У кого-нибудь есть хорошее предложение, как это обойти?

1 Ответ

1 голос
/ 24 апреля 2019

Документация fileInput() содержит подробности:

путь к данным

Путь к временному файлу, который содержит загруженные данные.Этот файл может быть удален, если пользователь выполняет другую операцию загрузки.

Это означает, что значение datapath, указанное во входной переменной, является временным файлом, который больше не доступен после закрытия приложения, котороечто попытается сделать функция readWorksheet.

Так что вам придется читать листы на сервере и как-то возвращать кадры данных.Я сделал это, определив второе реактивное значение, которое в основном представляет собой список фреймов данных, возвращаемых путем применения lapply на всех листах в wb, в этом случае 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()
...