2016-03-10 1 views
1

Я создаю веб-приложение, которое после загрузки файлов csv преобразует данные, а затем должно выводить несколько таблиц. Количество таблиц зависит строго от информации, включенной в файлы csv, поэтому вычисляется во время процесса преобразования данных. Я создал список lst с кадрами данных, которые должны быть выведены. Длина списка - это число таблиц, которые должны быть созданы. После поиска в Интернете я столкнулся с очень похожим вопросом (here), который, к сожалению, пока не ответил. У кого-нибудь есть идея, как его решить?Как создать динамический рендеринг Shiny R с количеством таблиц, определяемых загруженными CSV-файлами?

Некоторые из моего кода (не все, из-за значительного преобразования данных), где я хотел бы заменить фиксированный max_table с переменной length(data_set()):

library(shiny) 

ui <- fluidPage(
    fluidRow(column(3, 
        wellPanel(
        fileInput(inputId = "files", 
           label = "Choose cvs files", 
           accept=c('text/csv', 
             'text/comma-separated-values,text/plain', 
             '.csv'), 
           multiple = TRUE))), 
      column(5, offset = 1, 
        uiOutput("tables") 
       ) 
      ) 
) 

max_table <- 5 
server <- function(input,output){ 


    data_set <- reactive({ 
    if(is.null(input$files)){ 
     return(NULL) 
    } 

    lst <- list() 
    for(i in 1:length(input$files[,1])){ 
     lst[[i]] <- read.csv(input$files[[i, 'datapath']], sep = ",", header = TRUE, skip = 4, dec = ".") 
    } 
    lst 
    }) 

    output$tables <- renderUI({ 
    plot_output_list <- lapply(1:max_table, function(i) { 
     tablename <- paste("tablename", i, sep="") 
     tableOutput(tablename) 
    }) 
    do.call(tagList, plot_output_list) 
    }) 


    for (i in 1:max_table){ 
    local({ 
     my_i <- i 
     tablename <- paste("tablename", my_i, sep="") 
     output[[tablename]] <- renderTable({data_set()[[my_i]] 
     }) 
    })  
    } 
} 

shinyApp(ui = ui, server = server) 

Любая помощь будет высоко ценится!

ответ

2

Решение состоит в том, чтобы положить все внутри observe.

library(shiny) 

ui <- fluidPage(
    fluidRow(column(3, 
        wellPanel(
         fileInput(inputId = "files", 
            label = "Choose cvs files", 
            accept=c('text/csv', 
              'text/comma-separated-values,text/plain', 
              '.csv'), 
            multiple = TRUE))), 
      column(5, offset = 1, 
        uiOutput("tables") 
      ) 
    ) 
) 

server <- function(input,output){ 

    observe({ 
     if(!is.null(input$files)) { 
      max_table = length(input$files[,1]) 

      lst <- list() 
      for(i in 1:length(input$files[,1])){ 
       lst[[i]] <- read.csv(input$files[[i, 'datapath']], sep = ",", header = TRUE, skip = 4, dec = ".") 
      } 

      output$tables <- renderUI({ 
       plot_output_list <- lapply(1:max_table, function(i) { 
        tablename <- paste("tablename", i, sep="") 
        tableOutput(tablename) 
       }) 
       do.call(tagList, plot_output_list) 
      }) 

      for (i in 1:max_table){ 
       local({ 
        my_i <- i 
        tablename <- paste("tablename", my_i, sep="") 
        output[[tablename]] <- renderTable({lst[[my_i]] 
        }) 
       })  
      } 
     } 
    }) 

} 

shinyApp(ui = ui, server = server) 
+0

Большое спасибо, он отлично работает! –