Предотвращение ошибки Shiny R «аргумент имеет нулевую длину» при отображении первой строки таблицы с условием if-else и файлами SAS - PullRequest
0 голосов
/ 15 апреля 2019

Я написал приложение Shiny R. Я пытаюсь показать первую строку таблицы. Это работает, когда я загружаю файл Excel или CSV, однако, когда я загружаю файл SAS7BDAT или XPT, я получаю сообщение об ошибке: argument is of length zero. Этот обмен стека Ответ предполагает, что мне нужно проверить NULL и NA. Я также пытался это сделать, тестируя qctable для обоих условий, но все равно получаю сообщение об ошибке. Интересно, если я загружаю файл CSV или Excel, а затем загружаю файл SAS (любой), он работает правильно.

Соответствующий код:

#outputs the first row of the input file.
  output$firstrow <- renderText({
    req(qctable())
    if (filext() %in% c('.csv', '.txt')) {
      return(head(read_lines(input$qcfile$datapath), 1))
    } else if (
      (filext() %in% c('.xpt', '.sas7bdat')) | # This line and the next seem to be the issue
      (filext() %in% c('.xls', '.xlsx') & input$headers == TRUE)
    ) {
      return(paste0(names(qctable())))
    } else if ((filext() %in% c('.xls', '.xlsx') & input$headers == FALSE)) {
      return(paste0(qctable()[1,]))
    } else {
      return('Invalid file type!')
    }
  })

Мне удалось обойти это, включив условие файла SAS и условие файла Excel в различные тесты в предложении if, но это кажется неуклюжим.

Как и так:

  #outputs the first row of the input file.
  output$firstrow <- renderText({
    req(qctable())
    if (filext() %in% c('.csv', '.txt')) {
      return(head(read_lines(input$qcfile$datapath), 1))
    } else if (filext() %in% c('.xpt', '.sas7bdat')) {
      return(paste0(names(qctable()), collapse=('  ')))
    } else if (filext() %in% c('.xls', '.xlsx') & input$headers == TRUE) {
      return(paste0(names(qctable()), collapse=('  ')))
    } else if ((filext() %in% c('.xls', '.xlsx') & input$headers == FALSE)) {
      return(paste0(qctable()[1,], collapse=('  ')))
    } else {
      return('Invalid file type!')
    }
    })

Возможно, следует также отметить, что такая же ошибка возникает, если загружать файл неправильного типа, но работает правильно, если CSV / Excel загружен первым.

Полный код:

#### Libraries ####
library(shiny)
library(tidyverse)
library(readxl)
library(haven)

#### UI ####
ui <- fluidPage(
  # Sidebar with a slider input for number of bins 
  sidebarLayout(
    sidebarPanel(
      width = 3,
      # Input: Select a file 
      fileInput("qcfile", "Choose a File to QC",
                multiple = FALSE,
                accept = c("text/csv",
                           "text/comma-separated-values,text/plain",
                           ".csv",
                           '.txt',
                           '.xlsx',
                           '.xls',
                           '.xpt',
                           '.sas7bdat')),
      # Choose Separator
      htmlOutput('delimrb'),
      # Choose header values
      htmlOutput('header'),
      # Choose column TDxs are stored
      tags$strong('File Extension:'),
      verbatimTextOutput('file_ext')
    ),
    # Creates Main Panel with relevant tabs 
    mainPanel(width = 9,
      tabsetPanel(
        type = 'tabs',
        tabPanel('1st Row', verbatimTextOutput('firstrow'))
      ))
  )
)

#### Server #### 
server <- function(input, output) {
  #determines input file extention
  filext <- reactive({
    req(input$qcfile)
    fext <- tolower(str_extract(as.vector(input$qcfile$datapath), '\\.[^.]+$'))
    return(fext)
  })

  output$file_ext <- renderText(filext())

  # Sets UI for delimiter if input file is .csv or .txt
  output$delimrb <- renderUI({
    req(input$qcfile)
    if (filext() %in% c('.csv', '.txt')) {
      radioButtons("delimiter", "Delimiter for CSV/TXT",
                   choices = c(comma = ',',
                               pipe = '|',
                               tab = '\t')
      )
    }
  })

  # Sets UI for header if input file is not sas/xpt
  output$header <- renderUI({
    req(input$qcfile)
    if (filext() %in% c('.csv', '.txt', '.xlsx', '.xls')) {
      radioButtons('headers', 'Header row present?',
                   choices = c('Yes' = TRUE,
                               'No' = FALSE))
    }
  })

  #outputs the first row of the input file.
  output$firstrow <- renderText({
    req(qctable())
    if (filext() %in% c('.csv', '.txt')) {
      return(head(read_lines(input$qcfile$datapath), 1))
    } else if (
      (filext() %in% c('.xpt', '.sas7bdat')) | # This line and the next seem to be the issue
      (filext() %in% c('.xls', '.xlsx') & input$headers == TRUE)
    ) {
      return(paste0(names(qctable())))
    } else if ((filext() %in% c('.xls', '.xlsx') & input$headers == FALSE)) {
      return(paste0(qctable()[1,]))
    } else {
      return('Invalid file type!')
    }
  })

  # Creates Table from input file
  qctable <- reactive({
    req(input$qcfile)
    if (filext() %in% c('.csv', '.txt')){
      return(read_delim(file = input$qcfile$datapath,
                        delim = input$delimiter,
                        col_names = as.logical(input$headers),
                        col_types = cols(.default = 'c'))
      )
    } else if (filext() %in% c('.xls', '.xlsx')) {
      return(read_excel(path = input$qcfile$datapath,
                        col_names = as.logical(input$headers),
                        col_types = 'text'))
    } else if (filext() %in% c('.xpt')) {
      return(read_xpt(file = input$qcfile$datapath))
    } else if (filext() %in% c('.sas7bdat')){
      return(read_sas(data_file = input$qcfile$datapath))
    }
  })

}

#### Run the application ####
shinyApp(ui = ui, server = server)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...