R语言如何合并长度一致仅相差.或-的重复行名对应数据行
R语言按规则合并行名仅存在
./-差异的等长重复行 问题说明
处理data.frame时遇到行名重复问题:重复行仅在行名的.和-字符上有差异,示例数据构造代码如下:
df <- data.frame(cell1 = c(0,1,2,3,4,5,6,7), cell2 = c(0,1,2,3,4,5,6,7)) rownames(df) <- c("HLA.F", "HLA.G", "HLA.A", "HLA-F", "HLA-G", "HLA-A", "HLA-F-AS1", "HLA-E") df #> cell1 cell2 #> HLA.F 0 0 #> HLA.G 1 1 #> HLA.A 2 2 #> HLA-F 3 3 #> HLA-G 4 4 #> HLA-A 5 5 #> HLA-F-AS1 6 6 #> HLA-E 7 7
需要严格按照以下规则合并:
- 仅合并行名字符长度完全一致、除
.和-外其余字符完全相同的重复行 - 合并后统一保留带
.的版本作为最终行名 - 长度不同的相似行名(如示例中的
HLA-F-AS1)、无匹配重复项的行(如示例中的HLA-E)不做合并,原样保留
预期输出参考:
#> cell1 cell2 #> HLA.F 3 3 #> HLA.G 5 5 #> HLA.A 7 7 #> HLA-F-AS1 6 6 #> HLA-E 7 7
原有循环代码仅能实现部分重复项匹配,无法覆盖长度校验、无重复项保留的场景,原有代码如下:
for (i in unique(rownames(df))) { test <- grep(i, unique(rownames(df))) df.2 <- t(df[test,]) #get duplicated names df.2.cols <- colnames(df.2) #get name with period test.period <- grep("[.]",df.2.cols, value = TRUE) #merge them df.2 <- apply(df.2[,df.2.cols], 1, function(x) x[!is.na(x)][1]) df.2 <- t(as.data.frame(df.2)) rownames(df.2) <- test.period #remove duplicates and replace it with merged row df <- df[!(row.names(df) %in% df.2.cols), ] df <- rbind(df, df.2) }
实现代码
无需安装额外依赖包,直接用基础R函数即可实现,核心逻辑是先给每行生成唯一分组键,再按组聚合:
# 提取原始行名 raw_rn <- rownames(df) # 生成分组键:将.和-统一替换为相同字符+拼接行名长度,保证仅等长、仅.-差异的行分到同一组 group_id <- paste0(gsub("[.-]", "_", raw_rn), "_", nchar(raw_rn)) # 按分组聚合处理 df_merged <- do.call(rbind, lapply(split(seq_len(nrow(df)), group_id), function(row_idx) { group_rn <- raw_rn[row_idx] # 优先选取带.的行名作为合并后的行名,无带.的行名则保留原始行名 target_rn <- if (any(grepl("\\.", group_rn))) { grep("\\.", group_rn, value = TRUE) } else { group_rn } # 聚合取值:示例预期取同组靠后行的数值,若需要求和/取均值/最大值可直接修改此处逻辑 res <- df[tail(row_idx, 1), , drop = FALSE] rownames(res) <- target_rn res })) # 输出合并结果 print(df_merged)
聚合逻辑可按需调整:如果需要同组数值求和,将取值部分替换为
as.data.frame(t(colSums(df[row_idx, ])))即可;如果需要取均值替换为as.data.frame(t(colMeans(df[row_idx, ])))。
内容的提问来源于stack exchange,提问作者KaitS
相关产品推荐
相关产品推荐

