rendertext renderprint crear como r shiny

renderprint - ¿Cómo organizar grandes aplicaciones brillantes?



shiny dashboard (3)

¿Cuáles son las mejores prácticas para organizar aplicaciones Shiny más grandes?
Creo que las mejores prácticas de R también son aplicables a Shiny.
Las mejores prácticas de R se analizan aquí: Cómo organizar grandes programas de R
Enlace a la Guía de estilo R de Google: Guía de estilo

Pero, ¿cuáles son los consejos y trucos únicos en el contexto Shiny que puedo adoptar para que mi código Shiny se vea mejor (y más legible)? Estoy pensando en cosas como:

  • Explotar la programación orientada a objetos en Shiny
  • En server.R qué partes deben obtenerse?
  • Jerarquía de archivos del proyecto que contiene documentos de descuento, imágenes, xml y archivos fuente

Por ejemplo, si estoy usando navbarPage y tabsetPanel en cada tabPanel mi código comienza a verse bastante desordenado después de agregar varios elementos de la interfaz de usuario.

Código de ejemplo:

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)

Para organizar el código ui.R encontré una solución bastante buena de GitHub: código radiante
La solución es usar renderUI para renderizar cada tabPanel y en el server.R pestañas server.R se obtienen de diferentes archivos.

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)


Después de la adición de módulos a R brillante. La gestión de estructuras complejas en aplicaciones brillantes se ha vuelto mucho más fácil.

Descripción detallada de módulos brillantes: Here

Ventajas de usar módulos:

  • Una vez creados, se reutilizan fácilmente
  • Las colisiones de identificación son más fáciles de evitar
  • Organización del código basada en entradas y salidas de módulos.

En la aplicación brillante basada en pestañas, una pestaña puede considerarse como un módulo que tiene entradas y salidas . Las salidas de las pestañas se pueden pasar a otras pestañas como entradas.

Aplicación de archivo único para estructura basada en pestañas que explota el pensamiento modular. La aplicación se puede probar utilizando el conjunto de datos de cars . Partes del código se copiaron del Joe Cheng (primer enlace). Todos los comentarios son bienvenidos.

# 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)


Escribí Radiant. No he escuchado a la gente decir cosas malas sobre la organización del código (todavía), pero estoy seguro de que podría ser mejor. Una opción sería separar la interfaz de usuario y la lógica como lo hace Joe Cheng en parciales brillantes.

https://github.com/jcheng5/shiny-partials

Otra podría ser probar la programación OO, por ejemplo, usando R6 http://rpubs.com/wch/17459


Realmente me gusta cómo Matt Leonawicz organiza sus aplicaciones. Tomé su enfoque aprendiendo a usar Shiny, ya que todos sabemos que puede dispersarse bastante si no se maneja adecuadamente. Eche un vistazo a su estructura, da una visión general de la forma en que organiza las aplicaciones en la aplicación llamada run_alfresco

https://github.com/ua-snap/shiny-apps