R Tidyverse 批量自动识别合并tibble带...后缀的重复列
问题原因
使用read_delim()读取分隔符不规范的文件时,字段内存在未被识别的分隔符会导致单列被错误拆分为多列,readr会自动给重名列追加...2、...3格式的后缀。
之前尝试的固定截取列名前7位+group_by()的方案报错核心原因有两点:
group_by()是对数据的行维度做分组,输入的列名向量长度等于数据列数(示例中为10),和数据行数(示例中为407400)不匹配,触发长度校验错误- 固定截取前7位列名的逻辑鲁棒性极差,列名长度变化时会将完全无关的字段错误归为同一组,无法适配多文件批量处理的场景
实现代码
以下方案可自动识别同源拆分列,无需手动指定列位置或列名,完全匹配合并规则,可直接嵌入for循环做批量处理:
library(tidyverse) merge_split_cols <- function(df) { # 正则匹配移除列名末尾readr自动添加的...数字后缀,得到原始同源列名 raw_col_names <- str_remove(names(df), "\\.\\.\\.\\d+$") # 按原始列名拆分列索引分组 col_groups <- split(seq_along(df), raw_col_names) merged_cols <- map(col_groups, function(idx) { # 仅出现1次的非重复列直接原样返回 if (length(idx) == 1) return(df[[idx]]) sub_data <- df[, idx] # 数值类型列按规则合并:单非NA取该值、多非NA取均值、全NA返回NA if (all(map_lgl(sub_data, is.numeric))) { merged_val <- rowMeans(sub_data, na.rm = TRUE) merged_val[is.nan(merged_val)] <- NA return(merged_val) } # 非数值类型列逐行取第一个非NA值,适配字符、时间等类型列的拆分场景 apply(sub_data, 1, function(row) { valid_val <- row[!is.na(row)] if (length(valid_val) == 0) return(NA) return(valid_val[1]) }) }) # 拼装为最终tibble,保留原始列名 as_tibble(merged_cols, .name_repair = "minimal") } # 调用示例:处理单个数据框 # df_clean <- merge_split_cols(df) # 批量处理多文件时,在循环中读取文件后直接调用该函数即可
方案说明
- 同源列识别通过正则匹配后缀实现,不依赖固定列名长度、固定列位置,不同文件的拆分列位置、数量变化都能自动适配
- 数值列合并使用
rowMeans(na.rm = TRUE)实现,天然匹配需求规则:单行仅1个非NA值时计算结果就是该值,多个非NA值时自动计算均值,全NA时将返回的NaN替换为NA即可 - 非重复列不做任何处理,完全保留原有内容、数据类型和属性,比如示例中的
Date&Time、SNOWTHERMO#1#TS0_30MIN_MEAN这类列不会被修改 - 兼容非数值类型的拆分列场景,避免时间、字符类列被强制转数值报错
测试验证:对示例数据中的
SNOWDEPTH#1#HS...2和SNOWDEPTH#1#HS...3列,合并后第一行值为0、第二行值为10、第三行值为9、第四行值为NA,和预期结果完全一致。
内容的提问来源于stack exchange,提问作者Beat Pfund
相关产品推荐
相关产品推荐

