큰 Shiny 앱을 구성하는 방법은 무엇입니까?
더 큰 Shiny 애플리케이션을 구성하는 모범 사례는 무엇입니까?
최고의 R 관행이 Shiny에도 적용될 수 있다고 생각합니다.
R 모범 사례는 여기에서 설명합니다. 대규모 R 프로그램을 구성하는 방법
Google의 R 스타일 가이드 링크 : 스타일 가이드
그러나 Shiny 코드를 더보기 좋게 (그리고 더 읽기 쉽게) 만들기 위해 채택 할 수있는 Shiny 컨텍스트에서 고유 한 팁과 트릭은 무엇입니까? 나는 다음과 같은 것을 생각하고있다.
- Shiny에서 객체 지향 프로그래밍 활용
- 에서
server.R
어떤 부품 공급해야 하는가? - 마크 다운 문서, 그림, xml 및 소스 파일을 포함하는 프로젝트의 파일 계층 구조
예를 들어 내가 사용 navbarPage
하고 tabsetPanel
있고 모든 tabPanel
코드에서 여러 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에서 아주 좋은 솔루션을 찾았습니다. 빛나는 코드
솔루션은 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 광택 에 모듈 을 추가 한 후 . 반짝이는 애플리케이션에서 복잡한 구조를 관리하는 것이 훨씬 쉬워졌습니다.
반짝이는 모듈에 대한 자세한 설명 : 여기
모듈 사용의 장점 :
- 생성되면 쉽게 재사용 할 수 있습니다.
- ID 충돌은 피하는 것이 더 쉽습니다.
- 모듈의 입력 및 출력을 기반으로 한 코드 구성
탭 기반의 반짝이는 앱에서 하나의 탭은 입력 과 출력 이있는 하나의 모듈로 간주 될 수 있습니다 . 그런 다음 탭의 출력을 입력으로 다른 탭에 전달할 수 있습니다.
모듈 식 사고를 활용하는 탭 기반 구조용 단일 파일 앱. 자동차 데이터 세트 를 사용하여 앱을 테스트 할 수 있습니다 . 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)
Matt Leonawicz가 앱을 구성하는 방식이 정말 마음에 듭니다. 나는 Shiny를 사용하는 방법을 배우는 그의 접근 방식을 취했습니다. 우리 모두가 제대로 관리하지 않으면 상당히 흩어질 수 있다는 것을 알고 있기 때문입니다. 그의 구조를 살펴보면 run_alfresco 라는 앱에서 앱을 구성하는 방식에 대한 개요를 제공합니다.
https://github.com/ua-snap/shiny-apps
나는 Radiant를 썼다. 나는 사람들이 코드 구성에 대해 (아직) 나쁜 말을하는 것을들은 적이 없지만 그것이 더 나을 수 있다고 확신합니다. 한 가지 옵션은 Joe Cheng이 반짝이는 부분에서 수행하는 것처럼 ui와 논리를 분리하는 것입니다.
https://github.com/jcheng5/shiny-partials
Another might be to try OO programming, e.g., using R6 http://rpubs.com/wch/17459
ReferenceURL : https://stackoverflow.com/questions/27080089/how-to-organize-large-shiny-apps
'Programing' 카테고리의 다른 글
소켓 오류에서 더 이상 읽을 데이터가 없습니다. (0) | 2020.12.26 |
---|---|
두 개의 node.js 서버를 웹 소켓과 연결하는 방법은 무엇입니까? (0) | 2020.12.26 |
Team Foundation Server-기록과 함께 소스 이동 (0) | 2020.12.26 |
ASP.NET MVC에 JSON 데이터 게시 (0) | 2020.12.26 |
Cordova는 무엇이며 PhoneGap과 어떤 관련이 있습니까? (0) | 2020.12.26 |