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

R shiny如何将CSV底部行列转为表头并与上方数据并排展示

实现方案

核心处理逻辑

你需要先识别CSV文件中第二段表头的位置,拆分两段内容分别解析为独立数据框后再横向拼接,具体逻辑如下:

  • 上传文件时同时存储原始文本行内容,用于后续结构识别
  • 匹配第二段表头的特征(本例中表头开头为ID字段)定位拆分点
  • 两段数据分别解析后对齐行数,再横向拼接得到最终结果

修改后的完整app.R代码

library(shiny)
library(reshape2)
library(DT)
library(tibble)


###function for deleting the rows
splitColumn <- function(data, column_name) {
  newColNames <- c("Unmerged_type1", "Unmerged_type2")
  newCols <- colsplit(data[[column_name]], " ", newColNames)
  after_merge <- cbind(data, newCols)
  after_merge[[column_name]] <- NULL
  after_merge
}
###_______________________________________________
### function for inserting a new column

fillvalues <- function(data, values, columName){
  df_fill <- data
  vec <- strsplit(values, ",")[[1]]
  df_fill <- tibble::add_column(df_fill, newcolumn = vec, .after = columName)
  df_fill
}

##function for removing the colum

removecolumn <- function(df, nameofthecolumn){
  df[ , -which(names(df) %in% nameofthecolumn)]
}

### use a_splitme.csv for testing this program

ui <- fluidPage(
  sidebarLayout(
    sidebarPanel(
      fileInput("file1", "Choose CSV File", accept = ".csv"),
      checkboxInput("header", "Header", TRUE),
      actionButton("mergeTwoParts", "拼接双段表格", class = "btn-success"),
      actionButton("Splitcolumn", "SplitColumn", class = "btn-warning" ),
      uiOutput("selectUI"),
      
      
      actionButton("replacevalues", label = 'Replace values', class= "btn-Secondary"),
      actionButton("removecolumn", "Remove Column"),
      actionButton("Undo", 'Undo', style="color: #fff; background-color: #337ab7; border-color: #2e6da4"),
      actionButton("deleteRows", "Delete Rows"),
      textInput("textbox", label="Input the value to replace:"),
      actionButton('downloadbtn', label= 'Download'),
    ),
    mainPanel(
      DTOutput("table1")
    )
  )
)

server <- function(session, input, output) {
  rv <- reactiveValues(data = NULL, orig=NULL, raw_lines = NULL)
  
  observeEvent(input$file1, {
    file <- input$file1
    ext <- tools::file_ext(file$datapath)
    
    req(file)
    
    validate(need(ext == "csv", "Please upload a csv file"))
    
    rv$orig <- read.csv(file$datapath, header = input$header)
    rv$data <- rv$orig
    # 存储原始文本行用于双段结构识别
    rv$raw_lines <- readLines(file$datapath, encoding = "UTF-8")
  })
  
  # 双段表格拼接逻辑
  observeEvent(input$mergeTwoParts, {
    req(rv$raw_lines)
    # 定位两个表头的位置,匹配规则可根据实际表头调整
    header_pos <- which(grepl("^ID\\s+", rv$raw_lines))
    validate(need(length(header_pos) == 2, "未检测到两段独立表头的结构,请检查文件格式"))
    
    # 解析上段数据 空白分隔如果是逗号分隔请把sep改成","
    part1 <- read.table(text = rv$raw_lines[header_pos[1]:(header_pos[2]-1)], 
                        header = TRUE, sep = "", strip.white = TRUE)
    # 解析下段数据
    part2 <- read.table(text = rv$raw_lines[header_pos[2]:length(rv$raw_lines)], 
                        header = TRUE, sep = "", strip.white = TRUE)
    
    # 对齐两段数据的行数,不足的补NA
    max_row <- max(nrow(part1), nrow(part2))
    if(nrow(part1) < max_row) part1[(nrow(part1)+1):max_row, ] <- NA
    if(nrow(part2) < max_row) part2[(nrow(part2)+1):max_row, ] <- NA
    
    # 横向拼接,保留原列名
    rv$data <- cbind(part1, part2)
    colnames(rv$data) <- c(colnames(part1), colnames(part2))
  })
  
  output$selectUI<-renderUI({
    req(rv$data)
    selectInput(inputId='selectcolumn', label='select column', choices = names(rv$data))
  })
  
  
  observeEvent(input$Splitcolumn, {
    rv$data <- splitColumn(rv$data, input$selectcolumn)
  })
  
  observeEvent(input$deleteRows,{
    if (!is.null(input$table1_rows_selected)) {
      rv$data <- rv$data[-as.numeric(input$table1_rows_selected),]
    }
  })
  
  output$table1 <- renderDT(
    rv$data, selection = 'none', server = F, editable = T
  )
  #includes extra column after the 'select column' and replaces the values specified 'Input the value to replace:'
  observeEvent(input$replacevalues, {
    rv$data <- fillvalues(rv$data, input$textbox, input$selectcolumn)
  })
  #Removing the specifield column through select column
  observeEvent(input$removecolumn, {
    rv$data <- removecolumn(rv$data,input$selectcolumn)
  })
  observeEvent(input$Undo, {
    rv$data <- rv$orig
  })
  #Storing the csv file through download button
  observeEvent(input$downloadbtn,{
    write.csv(rv$data,'test.csv', row.names = FALSE)
    print ('file has been downloaded')
  })
  observeEvent(input$downloadbtn, {
    showModal(modalDialog(
      title = "Download Status.",
      paste0("csv file has been downloaded",input$downloadbtn,'.'),
      easyClose = TRUE,
      footer = NULL
    ))
  })
}

shinyApp(ui, server)

使用说明

  1. 上传符合格式的CSV文件后,点击「拼接双段表格」按钮即可自动完成两段数据的横向拼接
  2. 如果你的CSV是逗号分隔格式,将代码中read.table的sep = ""修改为sep = ","即可
  3. 点击「Undo」按钮可撤销拼接操作,回到原始上传的数据状态

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.25 00:06:04