如何用R按不同分隔符拆分数据框多列元素并拆分行?
拆分DataFrame多分隔符列并保留其余列内容的解决思路
需求说明
需要将DataFrame中的alt列(含中文逗号分隔的多个等位基因)和info列(含GT:AD结构,GT用斜杠分隔、AD用英文逗号分隔)拆分到不同行,同时保留其余列的内容,且拆分后info列需对应每个alt值生成0/n:ref_depth,alt_depth的格式。
输入数据
structure(list(ref = c("A", "C", "A", "G", "C"), alt = c("T,TAA,TAAAA,TAAAAA", "G,GC,GCCG", "T", "A G", "G"), chr = c("chr1", "chr1", "chr1", "chr1", "chr2"), pos_s = c(2313007, 2456780, 2578901, 2689511, 18907652), pos_e = c(2313009, 2456784, 2578903, 2689513, 18907654), format = c("GT:AD", "GT:AD", "GT:AD", "GT:AD", "GT:AD" ), info = c("0/1/2/3/4:296,5,33,29,55", "0/1/2/3:376,22,13,7", "0/1:323,24", "0/1:288,21", "0/1:3342,25")), class = c("tbl_df", "tbl", "data.frame"), row.names = c(NA, -5L))

期望输出数据
structure(list(ref = c("A", "A", "A", "A", "C", "C", "C", "A", "G", "C"), alt = c("T", "TAA", "TAAAA", "TAAAAA", "G", "GC", "GCCG", "T", "A G", "G"), chr = c("chr1", "chr1", "chr1", "chr1", "chr1", "chr1", "chr1", "chr1", "chr1", "chr2"), pos_s = c(2313007, 2313007, 2313007, 2313007, 2456780, 2456780, 2456780, 2578901, 2689511, 18907652), pos_e = c(2313009, 2313009, 2313009, 2313009, 2456784, 2456784, 2456784, 2578903, 2689513, 18907654), format = c("GT:AD", "GT:AD", "GT:AD", "GT:AD", "GT:AD", "GT:AD", "GT:AD", "GT:AD", "GT:AD", "GT:AD"), info = c("0/1:296,5", "0/2:296,33", "0/3:296,29", "0/4:296,55", "0/1:376,22", "0/2:376,13", "0/3:376,7", "0/1:323,24", "0/1:288,21", "0/1:3342,25")), class = c("tbl_df", "tbl", "data.frame" ), row.names = c(NA, -10L))

解决代码及说明
使用R的tidyverse工具集,通过分步拆分、映射匹配实现需求:
library(tidyverse) # 读取输入数据(若已加载可跳过) df <- structure(list(ref = c("A", "C", "A", "G", "C"), alt = c("T,TAA,TAAAA,TAAAAA", "G,GC,GCCG", "T", "A G", "G"), chr = c("chr1", "chr1", "chr1", "chr1", "chr2"), pos_s = c(2313007, 2456780, 2578901, 2689511, 18907652), pos_e = c(2313009, 2456784, 2578903, 2689513, 18907654), format = c("GT:AD", "GT:AD", "GT:AD", "GT:AD", "GT:AD" ), info = c("0/1/2/3/4:296,5,33,29,55", "0/1/2/3:376,22,13,7", "0/1:323,24", "0/1:288,21", "0/1:3342,25")), class = c("tbl_df", "tbl", "data.frame"), row.names = c(NA, -5L)) # 核心处理流程 result_df <- df %>% # 拆分alt列(注意使用中文逗号作为分隔符) separate_rows(alt, sep = ",") %>% # 将info列拆分为GT(基因型)和AD(深度)两部分 separate(info, into = c("GT", "AD"), sep = ":") %>% # 对每行的GT和AD进行映射处理,生成对应每个alt的info字符串 mutate( # 拆分GT为基因型向量,去掉第一个"0" gt_parts = str_split(GT, "/"), # 拆分AD为深度向量,第一个元素是参考深度,后续是各alt对应深度 ad_parts = str_split(AD, ","), # 组合生成匹配的info条目 info = map2_chr(gt_parts, ad_parts, function(g, a) { ref_ad <- a[1] alt_ad_list <- a[-1] gt_pair_list <- paste0("0/", g[-1]) paste0(gt_pair_list, ":", ref_ad, ",", alt_ad_list) }) ) %>% # 将info的向量拆分为多行,与alt的拆分结果对应 unnest(info) %>% # 清理中间生成的临时列 select(-GT, -AD, -gt_parts, -ad_parts) # 查看最终结果 print(result_df)
关键细节说明
- alt列拆分:注意输入中
alt使用的是中文逗号“,”,必须在separate_rows中指定sep = ",",否则无法正确拆分; - info列映射:通过
map2_chr将每行的基因型和深度一一对应,生成0/n:ref_depth,alt_depth格式的字符串,确保每个alt值匹配正确的info内容; - 行数对应:
separate_rows拆分alt后,原行的行数会扩展为alt的元素个数,再通过unnest将生成的info向量拆分为多行,保证每行的alt和info完全对应。
内容的提问来源于stack exchange,提问作者Pokemoon
相关产品推荐
相关产品推荐

