如何从 drake 计划将闪亮的应用程序部署到 shinyapps.io

How to deploy shiny app to shinyapps.io from drake plan

这是关闭将应用程序和数据传递给 Shiny 部署函数的循环的后续问题:

How to use shiny app as a target in drake

我想直接从 drake 计划部署一个闪亮的应用程序,如下所示。

library(drake)
library(shiny)

plan <- drake_plan(
  cars_data = mtcars,
  deployment = custom_deployment_function(file_in("app.R"), cars_data)
)

custom_shiny_deployment <- function(file, data_input) {

    rsconnect::deployApp(
    appFiles = file,
    appName = "cars",
    forceUpdate = TRUE
  )
}

Saved as "app.R" in project working directory (the app works outside of drake if data_input <- mtcars) :

shinyApp(
  ui = fluidPage(
    selectInput("variable", "Variable:",
                c("Cylinders" = "cyl",
                  "Transmission" = "am")),
    tableOutput("data")
  ),
  server = function(input, output) {
    output$data <- renderTable({
      data_input[, c("mpg", input$variable), drop = FALSE]
    }, rownames = TRUE)
  }
)

来自 shinyapps.io 的日志显示来自 drake 的“cars_data”没有被传递到 custom_deployment_function 环境中的 Shiny 服务器“data_input”:

2020-07-14T20:12:57.418989+00:00 shinyapps[2569696]: htmltools version: 0.5.0
2020-07-14T20:12:57.419186+00:00 shinyapps[2569696]: Using pandoc: /opt/connect/ext/pandoc2
2020-07-14T20:12:57.589960+00:00 shinyapps[2569696]: Using jsonlite for JSON processing
2020-07-14T20:12:57.593223+00:00 shinyapps[2569696]: 
2020-07-14T20:12:57.593224+00:00 shinyapps[2569696]: Starting R with process ID: '25'
2020-07-14T20:12:57.628389+00:00 shinyapps[2569696]: 
2020-07-14T20:12:57.628390+00:00 shinyapps[2569696]: Listening on http://127.0.0.1:38608
2020-07-14T20:13:14.686424+00:00 shinyapps[2569696]: Running on host: e89f96d02b6e
2020-07-14T20:13:14.691423+00:00 shinyapps[2569696]: Server version: 1.8.4-11
2020-07-14T20:13:14.691436+00:00 shinyapps[2569696]: LANG: en_US.UTF-8
2020-07-14T20:13:14.691436+00:00 shinyapps[2569696]: R version: 4.0.0
2020-07-14T20:13:14.691437+00:00 shinyapps[2569696]: shiny version: 1.5.0
2020-07-14T20:13:14.691467+00:00 shinyapps[2569696]: rmarkdown version: (none)
2020-07-14T20:13:14.691648+00:00 shinyapps[2569696]: Using pandoc: /opt/connect/ext/pandoc2
2020-07-14T20:13:14.691475+00:00 shinyapps[2569696]: knitr version: (none)
2020-07-14T20:13:14.857243+00:00 shinyapps[2569696]: Using jsonlite for JSON processing
2020-07-14T20:13:14.691443+00:00 shinyapps[2569696]: httpuv version: 1.5.4
2020-07-14T20:13:14.895595+00:00 shinyapps[2569696]: 
2020-07-14T20:13:14.691480+00:00 shinyapps[2569696]: jsonlite version: 1.7.0
2020-07-14T20:13:14.860404+00:00 shinyapps[2569696]: 
2020-07-14T20:13:14.860404+00:00 shinyapps[2569696]: Starting R with process ID: '41'
2020-07-14T20:13:14.895596+00:00 shinyapps[2569696]: Listening on http://127.0.0.1:42022
2020-07-14T20:13:14.691496+00:00 shinyapps[2569696]: RJSONIO version: (none)
2020-07-14T20:13:14.691506+00:00 shinyapps[2569696]: htmltools version: 0.5.0
2020-07-14T20:15:57.441648+00:00 shinyapps[2569696]: Running on host: a2e664ad9837
2020-07-14T20:15:57.447236+00:00 shinyapps[2569696]: Server version: 1.8.4-11
2020-07-14T20:15:57.447326+00:00 shinyapps[2569696]: R version: 4.0.0
2020-07-14T20:15:57.447337+00:00 shinyapps[2569696]: knitr version: (none)
2020-07-14T20:15:57.447337+00:00 shinyapps[2569696]: rmarkdown version: (none)
2020-07-14T20:15:57.447327+00:00 shinyapps[2569696]: shiny version: 1.5.0
2020-07-14T20:15:57.447260+00:00 shinyapps[2569696]: LANG: en_US.UTF-8
2020-07-14T20:15:57.447337+00:00 shinyapps[2569696]: httpuv version: 1.5.4
2020-07-14T20:15:57.447338+00:00 shinyapps[2569696]: jsonlite version: 1.7.0
2020-07-14T20:15:57.447338+00:00 shinyapps[2569696]: RJSONIO version: (none)
2020-07-14T20:15:57.667089+00:00 shinyapps[2569696]: 
2020-07-14T20:15:57.447494+00:00 shinyapps[2569696]: Using pandoc: /opt/connect/ext/pandoc2
2020-07-14T20:15:57.630039+00:00 shinyapps[2569696]: Starting R with process ID: '24'
2020-07-14T20:15:57.626886+00:00 shinyapps[2569696]: Using jsonlite for JSON processing
2020-07-14T20:15:57.447347+00:00 shinyapps[2569696]: htmltools version: 0.5.0
2020-07-14T20:15:57.630037+00:00 shinyapps[2569696]: 
2020-07-14T20:15:57.667090+00:00 shinyapps[2569696]: Listening on http://127.0.0.1:40107
2020-07-14T20:16:14.758082+00:00 shinyapps[2569696]: Warning: Error in renderTable: object 'data_input' not found
2020-07-14T20:16:14.772348+00:00 shinyapps[2569696]:   108: renderTable [/srv/connect/apps/cars/app.R#13]
2020-07-14T20:16:14.772349+00:00 shinyapps[2569696]:   107: func
2020-07-14T20:16:14.772350+00:00 shinyapps[2569696]:    94: origRenderFunc
2020-07-14T20:16:14.772350+00:00 shinyapps[2569696]:    93: output$data
2020-07-14T20:16:14.772350+00:00 shinyapps[2569696]:    13: runApp
2020-07-14T20:16:14.772351+00:00 shinyapps[2569696]:    12: fn
2020-07-14T20:16:14.772351+00:00 shinyapps[2569696]:     7: connect$retry
2020-07-14T20:16:14.772352+00:00 shinyapps[2569696]:     6: eval
2020-07-14T20:16:14.772352+00:00 shinyapps[2569696]:     5: eval

抱歉,如果这是微不足道的,但在 drake 和 shiny 之间,它正在逃避我。

既然我看到了您部署应用程序的方式,我可以说这是预期的行为。是的,您的 custom_shiny_deployment() 可以访问数据,但部署的应用程序不能,因为 rsconnect::deployApp() 不从调用环境发送对象。如果您希望应用程序可以使用数据,我建议保存它(并使用 file_in()file_out() 跟踪它)然后将其传递给 deployApp()appFiles 参数通过 custom_shiny_deployment().

编辑

你的 app.R 可以保持原样。

app.R和你写的一样

library(shiny)

cars_data <- readRDS("cars_data.RDS")

shinyApp(
  ui = fluidPage(
    selectInput("variable", "Variable:",
                c("Cylinders" = "cyl",
                  "Transmission" = "am")),
    tableOutput("data")
  ),
  server = function(input, output) {
    output$data <- renderTable({
      cars_data[, c("mpg", input$variable), drop = FALSE]
    }, rownames = TRUE)
  } 
)

但是从 drake 的角度来看,您需要 file_in()file_out() 来确保正确的目标 运行 以正确的顺序和响应变化到 cars_data.RDSapp.R.

library(drake)

plan <- drake_plan(
  cars_data = mtcars,
  save_cars = saveRDS(cars_data, file_out("cars_data.RDS")),
  deployment = rsconnect::deployApp(
    appFiles = file_in("app.R", "cars_data.RDS"),
    appName = "cars",
    forceUpdate = TRUE
  )
)

make(plan)

如果你真的想让 appFiles 变成 NULLdrake 仍然需要 file_in() 所以它知道依赖于物理文件。

plan <- drake_plan(
  cars_data = mtcars,
  save_cars = saveRDS(cars_data, file_out("cars_data.RDS")),
  deployment = deploy_app(file_in("cars_data.RDS", "app.R"))
)

deploy_app <- function(...) {
  rsconnect::deployApp(
    appFiles = NULL,
    appName = "cars",
    forceUpdate = TRUE
  )
}

无论哪种方式,我建议先使用 plot()vis_drake_graph() 检查计划,然后再使用 make() 运行 检查计划。上面的两个计划都显示了数据文件的 deployment 下游(带有传入箭头),这正是我们想要的。

plot(plan)

如果没有这些文件标记,drake 可能会在数据准备好之前部署应用程序。

disconnected_plan <- drake_plan(
  cars_data = mtcars,
  saveRDS(cars_data, "cars_data.RDS"),
  deployment =  rsconnect::deployApp(
    appFiles = NULL,
    appName = "cars",
    forceUpdate = TRUE
  )
)

plot(disconnected_plan)