R Shiny, fileInput отображает «Загрузка завершена» за несколько секунд до того, как это будет фактически сделано - PullRequest
0 голосов
/ 08 февраля 2019

Мне обычно нужно загружать большие (~ 700 МБ) файлы CSV в мое блестящее приложение.Проблема в том, что он показывает «Загрузка завершена» менее чем за 3 секунды или около того, хотя на самом деле это занимает около 20 секунд (также подтвердили это, напечатав несколько строк данных).

Есть ли обходной путь дляэтот?

ui <- fluidPage( 

  titlePanel("Predictive Models"),

  # Sidebar layout with input and output definitions ----
  sidebarLayout(
    # Sidebar panel for inputs ----
    sidebarPanel(
      # Input: Select a file ----
      fileInput("file1", "Choose CSV File",
                multiple = FALSE,
                accept = c("text/csv",
                           "text/comma-separated-values,text/plain",
                           ".csv"),
                width = "80%")
       ...
server <- function(input, output) {

  values <- reactiveValues(df_data = NULL, station_id= NULL, station_name= NULL, station_data=NULL, processed_data=NULL,df=NULL)

  observeEvent(input$file1, {
    values$df_data <- read.csv(input$file1$datapath);

    output$sum <- renderPrint({
      print(head(values$df_data, 10))
    }) 
  }) 

1 Ответ

0 голосов
/ 10 февраля 2019

Загрузка файла выполняется в 2 этапа.

  1. Файл помещается во временную папку, определенную как tempdir ()
  2. Файл считывается в память с использованием read.csv()

Панель загрузки, которую мы видим в fileInput, измеряет только время загрузки файла на сервер и во временный каталог.Не время читать это в память.

Поскольку read.csv() блокирует сервер до завершения операции, единственный способ измерить время чтения файла в память - это прочитать файл в пакетном режиме.На каждом шаге мы регистрируем прогресс, используя Progress.

Вот пример, это не самый эффективный код.

library(shiny)

ui <- fluidPage( 

  titlePanel("Predictive Models"),

  # Sidebar layout with input and output definitions ----
  sidebarLayout(
    # Sidebar panel for inputs ----
    sidebarPanel(
      # Input: Select a file ----
      fileInput("file1", "Choose CSV File",
                multiple = FALSE,
                accept = c("text/csv",
                           "text/comma-separated-values,text/plain",
                           ".csv"),
                width = "80%")
    ),
    mainPanel(verbatimTextOutput("sum"))
  )
)

server <- function(input, output,session) {
  options(shiny.maxRequestSize=800*1024^2) 

  read_batch_with_progress = function(file_path,nrows,no_batches){
    progress = Progress$new(session, min = 1,max = no_batches)
    progress$set(message = "Reading ...")
    seq_length = ceiling(seq.int(from = 2, to = nrows-2,length.out = no_batches+1))
    seq_length = seq_length[-length(seq_length)]

    #read the first line
    df = read.csv(file_path,skip = 0,nrows = 1)
    col_names = colnames(df)

    for(i in seq_along(seq_length)){
      progress$set(value = i)
      if(i == no_batches) chunk_size = -1 else chunk_size = seq_length[i+1] - seq_length[i]

      df_temp = read.csv(file_path, skip = seq_length[i], nrows = chunk_size,header = FALSE,stringsAsFactors = FALSE)
      colnames(df_temp) = col_names
      df = rbind(df,df_temp)
    }

    progress$close()
    return(df)
  }


  df = reactive({
    req(input$file1)
    n_rows = length(count.fields(input$file1$datapath))

    df_out = read_batch_with_progress(input$file1$datapath,n_rows,10)

    return(df_out)
  })

  observe({
    output$sum <- renderPrint({
      print(head(df(), 10))
    }) 
  }) 
}

shinyApp(ui,server)

Этот код разбивает файл на 10 частей ичитает каждый блок в память, добавляя его к предыдущему фрагменту.На каждом шаге он регистрирует прогресс, используя progress$set(value = i)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...