gpt4 book ai didi

r - 如何组织大型 Shiny 应用程序?

转载 作者:行者123 更新时间:2023-12-03 05:44:39 25 4
gpt4 key购买 nike

组织大型 Shiny 应用程序的最佳实践是什么?
我认为最佳 R 实践也适用于 Shiny。
此处讨论最佳 R 实践:How to organize large R programs
链接至 Google 的 R 风格指南:Style Guide

但是在 Shiny 上下文中我可以采用哪些独特的提示和技巧来使我的 Shiny 代码看起来更好(并且更具可读性)?我正在考虑这样的事情:

  • 在 Shiny 中利用面向对象编程
  • server.R 中应采购哪些部分?
  • 项目的文件层次结构,包含 Markdown 文档、图片、xml 和源文件

例如,如果我在每个 tabPanel 中使用 navbarPagetabsetPanel,则在添加几个 UI 元素后,我的代码开始看起来相当困惑.

示例代码:

server <- function(input, output) {

#Here functions and outputs..

}

ui <- shinyUI(navbarPage("My Application",
tabPanel("Component 1",
sidebarLayout(
sidebarPanel(
# UI elements..
),
mainPanel(
tabsetPanel(
tabPanel("Plot", plotOutput("plot")
# More UI elements..
),
tabPanel("Summary", verbatimTextOutput("summary")
# And some more...
),
tabPanel("Table", tableOutput("table")
# And...
)
)
)
)
),
tabPanel("Component 2"),
tabPanel("Component 3")
))

shinyApp(ui = ui, server = server)

为了组织 ui.R 代码,我从 GitHub 找到了非常好的解决方案:radiant code
解决方案是使用 renderUI 渲染每个 tabPanel,并且在 server.R 中,选项卡源自不同的文件。

server <- function(input, output) {

# This part can be in different source file for example component1.R
###################################
output$component1 <- renderUI({
sidebarLayout(
sidebarPanel(
),
mainPanel(
tabsetPanel(
tabPanel("Plot", plotOutput("plot")),
tabPanel("Summary", verbatimTextOutput("summary")),
tabPanel("Table", tableOutput("table"))
)
)
)
})
#####################################

}
ui <- shinyUI(navbarPage("My Application",
tabPanel("Component 1", uiOutput("component1")),
tabPanel("Component 2"),
tabPanel("Component 3")
))

shinyApp(ui = ui, server = server)

最佳答案

模块添加到 R 后 Shiny 。在 Shiny 的应用程序中管理复杂结构变得更加容易。

Shiny 模块详细说明:Here

Advantages of using modules:

  • Once created, they are easily reused
  • ID collisions is easier to avoid
  • Code organization based on inputs and output of modules

在基于选项卡的 Shiny 应用程序中,一个选项卡可以被视为具有输入输出的一个模块。然后选项卡的输出可以作为输入传递到其他选项卡。

基于选项卡的结构的单文件应用程序,利用模块化思维。可以使用cars来测试应用程序数据集。部分代码复制自 Joe Cheng(第一个链接)。欢迎所有评论。

# Tab module
# This module creates new tab which renders dataTable

dataTabUI <- function(id, input, output) {
# Create a namespace function using the provided id
ns <- NS(id)

tagList(sidebarLayout(sidebarPanel(input),

mainPanel(dataTableOutput(output))))

}

# Tab module
# This module creates new tab which renders plot
plotTabUI <- function(id, input, output) {
# Create a namespace function using the provided id
ns <- NS(id)

tagList(sidebarLayout(sidebarPanel(input),

mainPanel(plotOutput(output))))

}

dataTab <- function(input, output, session) {
# do nothing...
# Should there be some logic?


}

# File input module
# This module takes as input csv file and outputs dataframe
# Module UI function
csvFileInput <- function(id, label = "CSV file") {
# Create a namespace function using the provided id
ns <- NS(id)

tagList(
fileInput(ns("file"), label),
checkboxInput(ns("heading"), "Has heading"),
selectInput(
ns("quote"),
"Quote",
c(
"None" = "",
"Double quote" = "\"",
"Single quote" = "'"
)
)
)
}

# Module server function
csvFile <- function(input, output, session, stringsAsFactors) {
# The selected file, if any
userFile <- reactive({
# If no file is selected, don't do anything
validate(need(input$file, message = FALSE))
input$file
})

# The user's data, parsed into a data frame
dataframe <- reactive({
read.csv(
userFile()$datapath,
header = input$heading,
quote = input$quote,
stringsAsFactors = stringsAsFactors
)
})

# We can run observers in here if we want to
observe({
msg <- sprintf("File %s was uploaded", userFile()$name)
cat(msg, "\n")
})

# Return the reactive that yields the data frame
return(dataframe)
}
basicPlotUI <- function(id) {
ns <- NS(id)
uiOutput(ns("controls"))

}
# Functionality for dataselection for plot
# SelectInput is rendered dynamically based on data

basicPlot <- function(input, output, session, data) {
output$controls <- renderUI({
ns <- session$ns
selectInput(ns("col"), "Columns", names(data), multiple = TRUE)
})
return(reactive({
validate(need(input$col, FALSE))
data[, input$col]
}))
}

##################################################################################
# Here starts main program. Lines above can be sourced: source("path-to-module.R")
##################################################################################

library(shiny)


ui <- shinyUI(navbarPage(
"My Application",
tabPanel("File upload", dataTabUI(
"tab1",
csvFileInput("datafile", "User data (.csv format)"),
"table"
)),
tabPanel("Plot", plotTabUI(
"tab2", basicPlotUI("plot1"), "plotOutput"
))

))


server <- function(input, output, session) {
datafile <- callModule(csvFile, "datafile",
stringsAsFactors = FALSE)

output$table <- renderDataTable({
datafile()
})

plotData <- callModule(basicPlot, "plot1", datafile())

output$plotOutput <- renderPlot({
plot(plotData())
})
}


shinyApp(ui, server)

关于r - 如何组织大型 Shiny 应用程序?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27080089/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com