如何基于键合并字符串?R语言分段序列拼接技术问询
解决方案:按TP<分组合并序列字符串
要实现将每个以TP<开头的分段对应的子行序列合并为完整字符串,并生成目标数据框out,可以通过分组标识+序列合并的思路来处理,以下提供两种实现方式(dplyr和base R):
方法1:使用dplyr包(简洁直观)
首先加载dplyr,然后通过分组标识将数据按TP<开头的行分组,再对每个组内的子序列进行合并,最后赋值到join列:
library(dplyr) # 原始数据框 df <- structure(list(position = structure(c(6L, 1L, 2L, 3L, 4L, 5L, 1L, 2L, 7L, 1L, 2L, 3L, 4L, 8L, 1L, 2L, 3L, 4L), .Label = c("1,2,3,4,5,6,7,8,9,10,11,12,13,14,15", "2,3,4,5,6,7,8,9,10,11,12,13,14,15,16", "3,4,5,6,7,8,9,10,11,12,13,14,15,16,17", "4,5,6,7,8,9,10,11,12,13,14,15,16,17,18", "TP<AMB88", "TP<AMT55", "TP<ELANE", "TP<RACK1"), class = "factor"), col = structure(c(15L, 6L, 3L, 11L, 5L, 14L, 9L, 18L, 16L, 8L, 13L, 4L, 2L, 17L, 7L, 12L, 1L, 10L), .Label = c("EQMTLRGTLKGHNGW", "GRRLACLFLACVLPA", "GSLSNYALLQLTLTA", "LGRRLACLFLACVLP", "LSNYALLQLTLTAFL", "MGSLSNYALLQLTLT", "MTEQMTLRGTLKGHN", "MTLGRRLACLFLACV", "MVKETTYYDVLGVKP", "QMTLRGTLKGHNGWV", "SLSNYALLQLTLTAF", "TEQMTLRGTLKGHNG", "TLGRRLACLFLACVL", "TP<AMB88", "TP<AMT55", "TP<ELANE", "TP<RACK1", "VKETTYYDVLGVKPN"), class = "factor")), class = "data.frame", row.names = c(NA, -18L)) # 处理流程 out <- df %>% # 生成分组ID:每个TP<开头的行为新组的起始 mutate(group_id = cumsum(grepl("^TP<", position))) %>% group_by(group_id) %>% mutate( # 合并组内子序列:第一个子序列 + 后续每个子序列的最后一个字符 full_seq = if (n() > 1) { sub_seqs <- as.character(col[-1]) paste0(sub_seqs[1], paste0(sapply(sub_seqs[-1], function(x) substr(x, nchar(x), nchar(x))), collapse = "")) } else "", # 赋值join列:标题行取自身position,第一个子行取合并后的序列,其余为空 join = case_when( row_number() == 1 ~ as.character(position), row_number() == 2 ~ full_seq, TRUE ~ "" ) ) %>% ungroup() %>% # 移除中间辅助列 select(-group_id, -full_seq) # 可选:将join列转为factor(与目标out格式匹配) out$join <- factor(out$join, levels = unique(out$join)[nchar(unique(out$join)) > 0])
方法2:使用base R(无需额外包)
如果不想加载dplyr,可以用base R的循环和分组处理实现:
# 原始数据框 df <- structure(list(position = structure(c(6L, 1L, 2L, 3L, 4L, 5L, 1L, 2L, 7L, 1L, 2L, 3L, 4L, 8L, 1L, 2L, 3L, 4L), .Label = c("1,2,3,4,5,6,7,8,9,10,11,12,13,14,15", "2,3,4,5,6,7,8,9,10,11,12,13,14,15,16", "3,4,5,6,7,8,9,10,11,12,13,14,15,16,17", "4,5,6,7,8,9,10,11,12,13,14,15,16,17,18", "TP<AMB88", "TP<AMT55", "TP<ELANE", "TP<RACK1"), class = "factor"), col = structure(c(15L, 6L, 3L, 11L, 5L, 14L, 9L, 18L, 16L, 8L, 13L, 4L, 2L, 17L, 7L, 12L, 1L, 10L), .Label = c("EQMTLRGTLKGHNGW", "GRRLACLFLACVLPA", "GSLSNYALLQLTLTA", "LGRRLACLFLACVLP", "LSNYALLQLTLTAFL", "MGSLSNYALLQLTLT", "MTEQMTLRGTLKGHN", "MTLGRRLACLFLACV", "MVKETTYYDVLGVKP", "QMTLRGTLKGHNGWV", "SLSNYALLQLTLTAF", "TEQMTLRGTLKGHNG", "TLGRRLACLFLACVL", "TP<AMB88", "TP<AMT55", "TP<ELANE", "TP<RACK1", "VKETTYYDVLGVKPN"), class = "factor")), class = "data.frame", row.names = c(NA, -18L)) # 初始化分组ID和join列 df$group_id <- cumsum(grepl("^TP<", df$position)) df$join <- "" # 遍历每个分组处理 for (g in unique(df$group_id)) { group_rows <- which(df$group_id == g) # 标题行赋值 df$join[group_rows[1]] <- as.character(df$position[group_rows[1]]) # 有子行时合并序列 if (length(group_rows) > 1) { sub_cols <- as.character(df$col[group_rows[-1]]) full_seq <- sub_cols[1] if (length(sub_cols) > 1) { full_seq <- paste0(full_seq, paste0(sapply(sub_cols[-1], function(x) substr(x, nchar(x), nchar(x))), collapse = "")) } # 赋值给第一个子行 df$join[group_rows[2]] <- full_seq } } # 生成最终输出数据框,移除辅助列 out <- df[, c("position", "col", "join")] # 可选:转为factor格式匹配目标 out$join <- factor(out$join, levels = unique(out$join)[nchar(unique(out$join)) > 0])
关键逻辑说明
- 分组标识:通过
cumsum(grepl("^TP<", position))为每个以TP<开头的行创建独立分组ID,后续子行自动归为同一组。 - 序列合并:每个子行的字符串是前一个子行去掉首字符、新增末尾字符,因此合并时只需取第一个子行的完整字符串,加上后续每个子行的最后一个字符即可得到完整序列。
- join列赋值:标题行的
join取自身position值,第一个子行取合并后的完整序列,其余子行留空,与目标格式完全匹配。
内容的提问来源于stack exchange,提问作者Learner
相关产品推荐
相关产品推荐

