闪亮的应用程序和嵌入在 R 包中的数据

Shiny app and data embedded in an R package

该软件包嵌入了一个闪亮的应用程序和一个数据集。包源在 GitHub.

嵌入式数据集用于填充ui(字段Input1)和数据集(在data/data_test.rda中,数据框有3个字段{year_p,model_p, volume_p}) 加载包时以惰性方式加载(描述文件参数 LazyData 设置为 true)。

此数据在整个会话期间保持不变,因此我不想为其创建反应函数。 问题 是,如果我使用数据集来填充 ui,程序包将不会 build,并且会在 bui丁丁

我考虑的备选方案是:

  1. 有一个反应函数(model_reactive())和一个在server.R中定义的observeEvent/updateSelectInput,但这看起来确实效率低下。顺便说一句,有没有办法让反应函数只计算一次?

  2. 将操作数据集的代码放在 global.R 中,以便数据可用于 server.R 和 ui.R

  3. 也许这个解释了如何处理环境,但我没明白。

ui.R

r shiny::selectInput("Input1", "Input1:", choices = model_ls, multiple = F, selectize = F) # error when building the package # ERROR: lazy loading failed for package 'TESTshinyapp'

server.R

r model_ls <- input_model(dat)

input.R

r input_model <- function(data) {dplyr::select(data, model_p) %>% dplyr::distinct() %>% unlist()}

问题的根源在于,当您的包的函数被解析时,您的数据集 data_test 超出了范围。这种行为是预期的,大多数包通过使用根据需要动态加载数据集的函数来解决这个问题。

一个简单的解决方法就是这样做:将应用程序的 ui 定义为函数

library(shiny)

ui <- function() {
  data(data_test, package = "TESTshinyapp")
  fluidPage(
    "Names of the dataset: ", 
    paste(names(data_test), collapse = ", ")
  )
}

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

}

shinyApp(ui(), server)

这样,当应用程序启动时,数据将像在服务器中一样动态加载。 (注意:在您的实际包中,sidebar 也需要转换成一个函数才能使它工作。)

另一种可能是加载launchApp中的数据,然后 用 factory pattern 创建 uiserver。换句话说:数据集被放入 launchApp 范围内,然后作为参数传递给工厂。

server_factory <- function(myData) {
  function(input, output, session) {
    ## use myData here as you please
  }
}

ui_factory <- function(myData) {
  fluidPage(
    "Names of the dataset: ", 
    paste(names(myData), collapse = ", ")
  )
}

launchApp <- function() {
  data(data_test, package = "TESTshinyapp")

  shinyApp(
    ui_factory(data_test),
    server_factory(data_test)
  )
}

launchApp()

此模式还允许您为 launchApp 定义参数,并根据需要将它们传递给工厂。