如何将由多个文件组成的Shiny应用程序转换为易于共享和可重复使用的Shiny示例?

29

在Stack Overflow上,有关于如何创建最小、完整、可验证的示例的资源,以及如何创建一个出色的R可重现的示例。然而,在问题方面没有类似的指南,遵循某些标准可以更有可能得到高质量的答案,从而解决您的问题。

然而,提出一个好的Shiny问题可能会很困难。应用程序通常是庞大且复杂的,使用多个数据源,并且代码通常分散在多个文件中,这使得与他人轻松共享可重现的代码变得困难。即使问题可能是由server.R引起的,但没有ui.R的内容(以及可能是样式表或global.R等其他文件)的示例是不可重现的。逐个复制所有这些文件的内容很麻烦,并且需要其他用户重新创建相同的文件结构才能重现该问题。
那么,如何将您的应用程序转换为良好的可重现示例?

3
这个问题是否更适合在元站点提问? - Wonko the Sane
2
可能是吧,但我可能不是最好的评判者,因为我很少访问元站。帮助中心在定义适合于Stack Overflow的“好”问题方面非常广泛。我在这里提出这个问题的原因主要是因为关于rpandas的类似问题也在Stack Overflow上而不是在元站上,所以我认为这是正确的做法。 - Florian
1
@Pac0 我理解你的观点,但我不确定是否完全同意。也许将这个讨论从评论区转移到Meta上的讨论,以获取其他人对于这个问题和类似问题的看法,是一个好主意。 - Florian
1个回答

28

示例数据

当创建与Shiny相关的问题时,所有关于样本数据的指南都适用于答案中提到的“如何创建一个出色的R可重现示例”。总结一下:确保运行代码不需要额外的文件。使用像mtcars这样的示例数据集,或者使用data.frame()创建一些示例数据。如果您的数据非常复杂,并且该复杂性确实需要说明问题,您也可以使用dput()。避免使用像read.csv()这样的函数,除非您有与fileInput等函数相关的问题。

示例代码

始终将代码减少到最小,以重现错误或意外行为。这包括删除对其他.CSS文件和.js文件的调用,并删除uiserver中不必要的函数。

Shiny应用程序通常由两个或三个文件(ui.Rserver.R和可能的global.R)组成,例如此演示应用程序。但是,最好将代码发布为单个脚本,以便其他人可以轻松运行而无需手动创建这些文件。这可以通过以下方式轻松完成:

  • 使用ui <- fluidPage(…)包装您的UI界面,
  • 使用server <- function(input,output, session) {…}创建服务器,
  • 然后调用shinyApp(ui, server)

因此,一个简单的骨架可以如下所示:

library(shiny)

ui <- fluidPage(

  )

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

}

shinyApp(ui, server)

工作示例

因此,考虑到上述所有内容,一个良好的Shiny应用程序的最小、完整和可验证示例可能如下所示:

library(shiny)

df <- data.frame(id = letters[1:10], value = seq(1,10))

ui <- fluidPage(
  sliderInput('nrow', 'Number of rows', min = 1, max = 10, value = 5),
  dataTableOutput('my_table')
  )

server <- function(input, output, session) {
  output$my_table <- renderDataTable({
    df[1:input$nrow,]
  })
}

shinyApp(ui, server)

添加CSS

有多种方法可以向Shiny应用程序添加自定义CSS,如这里所述。在可重现的示例中向Shiny应用程序添加CSS的首选方式是将CSS添加到代码中,而不是单独的文件中。这可以通过在应用程序的ui中添加一行来完成,例如:

tags$head(tags$style(HTML('body {background-color: lightblue;}'))),

我认为函数shinyUI已经过时且不必要。 - GyD
@GyD,我认为你是对的,我已经相应地更新了答案。 - Florian
@Florian。也许你可以解决一下应用程序何时需要加载文件的问题。 - MLavoie
@MLavoie,好建议,我希望用"If your data is very complex and that complexity is really required to illustrate the issue, you could also use dput(). Avoid using functions like read.csv()..."来表达。你认为这样就可以了吗?还是你有其他想法? - Florian
是的,我认为那样做可以。 - MLavoie

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接