You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Shiny应用CSV导入异常:分隔符无响应、列未拆分问题求助

修复Shiny应用CSV导入分隔符无响应及列合并问题

问题根源

  • 仅在文件上传时触发CSV读取逻辑,修改分隔符输入框后未重新读取文件,导致分隔符变更不生效
  • 若CSV文件使用非逗号分隔符,初始用默认逗号读取会导致所有内容合并为一列

修复方案

  1. 新增对分隔符输入框的监听,修改分隔符后自动重新读取CSV文件
  2. 将文件读取逻辑封装为响应式表达式,让文件上传、分隔符变更都能触发数据更新
  3. 确保列选择器、表格展示能正确响应数据变化

修复后完整代码

library(shiny)
library(readxl)
library(shinythemes)
library(plotly)
library(htmlwidgets)
library(IRdisplay)
library(shinyjs)
library(bslib) 
library(reactable)

shinyUI(
  tagList(
    useShinyjs(),
    tags$head(
      tags$link(rel = "stylesheet", type = "text/css", href = "style.css")
    ),
    navbarPage(
      theme = shinythemes::shinytheme("superhero"), "shinythemes",
      
      tabPanel("Data Sources", 
               sidebarLayout(
                 sidebarPanel(
                   fileInput("file", "Choose CSV or Excel File",
                             multiple = FALSE,
                             accept = c(
                               "text/csv",
                               "text/comma-separated-values,text/plain",
                               ".csv",
                               ".xlsx",  # Add support for Excel files
                               ".xls"
                             )
                   ),
                   br(),
                   shinyjs::hidden(textInput("delimiter", "Enter Delimiter (e.g., , or ;)", ",")),
                   br(),
                   numericInput("minNumberRow", label = "Display number of rows:", value = 10),
                   selectInput("columns_select", "Select Columns:", choices = NULL, multiple = TRUE)
                 ),
                 
                 mainPanel(
                   tabsetPanel(
                     tabPanel("Tab 1-1",
                              h3("Dobrodošli na prvi tabPanel u prvoj Navbar Page!"),
                              uiOutput("table_1")
                     ),
                     tabPanel("Tab 1-2",
                              h3("Dobrodošli na drugi tabPanel u prvoj Navbar Page!")
                     ),
                     tabPanel("Tab 1-3",
                              h3("Dobrodošli na treći tabPanel u prvoj Navbar Page!")
                     )
                   )
                 )
               )
      ),
      
      tabPanel("Page 2",
               sidebarLayout(
                 sidebarPanel(
                   p(" sidebarPanel."),
                   
                   div(
                     sliderInput("slider", "Slider input:", 1, 100, 30),
                     class = "my-slider-class" 
                   ),
                   
                 ),
                 mainPanel(
                   tabsetPanel(
                     tabPanel("Tab 2-1",
                              h3("Navbar Page!")
                     ),
                     tabPanel("Tab 2-2",
                              h3(" Navbar Page 2!")
                     ),
                     tabPanel("Tab 2-3",
                              h3(" Navbar Page 3!")
                     )
                   )
                 )
               )
      ),
      
      tabPanel("Page 3",
               sidebarLayout(
                 sidebarPanel(
                   p("Ovo je sidebarPanel za prvi tabsetPanel u trećoj Navbar Page.")
                 ),
                 mainPanel(
                   tabsetPanel(
                     tabPanel("Tab 3-1",
                              h3("Dobrodošli na prvi tabPanel u trećoj Navbar Page!")
                     ),
                     tabPanel("Tab 3-2",
                              h3("Dobrodošli na drugi tabPanel u trećoj Navbar Page!")
                     ),
                     tabPanel("Tab 3-3",
                              h3("Dobrodošli na treći tabPanel u trećoj Navbar Page!")
                     )
                   )
                 )
               )
      )
    )
  )
)

shinyServer(function(input, output, session) {
  
  # 切换分隔符输入框可见性
  observeEvent(input$file, {
    if (!is.null(input$file) && grepl("\\.csv$", input$file$name)) {
      shinyjs::toggle("delimiter", condition = TRUE)
    } else {
      shinyjs::toggle("delimiter", condition = FALSE)
    }
  })
  
  # 响应式读取数据,文件或分隔符变化时自动触发
  df_data <- reactive({
    req(input$file)
    
    if (grepl("\\.csv$", input$file$name)) {
      delimiter <- ifelse(nchar(input$delimiter) > 0, input$delimiter, ",")
      read.csv(input$file$datapath, sep = delimiter, header = TRUE, stringsAsFactors = FALSE, na.strings = "")
    } else {
      read_excel(input$file$datapath, sheet = 1, col_names = TRUE)
    }
  })
  
  # 数据更新时同步更新列选择器
  observeEvent(df_data(), {
    updateSelectInput(session, "columns_select", choices = colnames(df_data()), selected = colnames(df_data()))
  })
  
  min_rows <- reactive({
    input$minNumberRow
  })
  
  output$table_1 <- renderUI({
    selected_columns <- input$columns_select
    
    if (!is.null(df_data()) && ncol(df_data()) > 0) {
      if (is.null(selected_columns) || length(selected_columns) == 0) {
        selected_columns <- colnames(df_data())
      }
      
      reactable(
        df_data()[, selected_columns, drop = FALSE],
        defaultPageSize = as.numeric(min_rows()),
        filterable = TRUE,
        searchable = TRUE,
        minRows = 10,
        style = list(
          backgroundColor = "#a3bcc0",
          color = "#000000"
        )
      )
    } else {
      reactable(data.frame(), defaultPageSize = 10)
    }
  })
  
})

# 若已将ui和server拆分到独立文件,可删除下方两行注释外的代码
# ui <- source("ui.R")$value
# server <- source("server.R")$value

shinyApp(ui = shinyUI, server = shinyServer)

内容的提问来源于stack exchange,提问作者Denmla

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.15 19:05:23