如何用tidyr解析VCF文件中FORMAT与Sample字段的动态列?
用tidyr解析GATK VCF的FORMAT对应Sample字段
核心思路
因为VCF每行的FORMAT字段内容不一致,无法直接统一拆分,所以先将FORMAT和对应Sample的冒号分隔内容拆分为键值对行,再转成宽格式列,完美适配不同行的FORMAT差异。
步骤与代码示例
1. 加载VCF数据
用data.table::fread快速加载,跳过注释行:
library(data.table) library(tidyr) library(dplyr) # 加载VCF,跳过##开头的注释行,自动识别#CHROM为表头 vcf_dt <- fread("your_gatk.vcf", skip = "##") # 修正首列列名(fread会把#CHROM读成X.CHROM) colnames(vcf_dt)[1] <- "CHROM"
2. 单Sample解析
假设你的Sample列名为Sample1,替换为实际列名即可:
# 转成tibble方便tidyr操作 vcf_tbl <- as_tibble(vcf_dt) # 解析FORMAT与Sample字段 vcf_parsed <- vcf_tbl %>% # 添加行号作为唯一标识,确保后续合并回原变异行 mutate(row_id = row_number()) %>% # 按冒号拆分FORMAT和Sample列,生成一一对应的键值对行 separate_rows(FORMAT, Sample1, sep = ":") %>% # 重命名列以便后续转宽格式 rename(format_key = FORMAT, sample_val = Sample1) %>% # 将键值对转成宽格式,缺失字段自动填充NA pivot_wider( id_cols = c(row_id, CHROM, POS, ID, REF, ALT, QUAL, FILTER, INFO), names_from = format_key, values_from = sample_val ) %>% # 移除临时行号 select(-row_id)
3. 多Sample解析
如果有多个Sample列(如Sample1、Sample2),先将Sample列转成长格式再处理:
vcf_parsed_multi <- vcf_tbl %>% mutate(row_id = row_number()) %>% # 将所有Sample列转成长格式,区分样本名与对应数据 pivot_longer( cols = starts_with("Sample"), # 匹配所有Sample开头的列,可替换为具体列向量 names_to = "sample_name", values_to = "sample_data" ) %>% # 拆分FORMAT与Sample数据为键值对 separate_rows(FORMAT, sample_data, sep = ":") %>% rename(format_key = FORMAT, sample_val = sample_data) %>% # 转宽格式,列名格式为「样本名_字段名」(如Sample1_GT) pivot_wider( id_cols = c(row_id, CHROM, POS, ID, REF, ALT, QUAL, FILTER, INFO), names_from = c(sample_name, format_key), values_from = sample_val, names_sep = "_" ) %>% select(-row_id)
关键说明
separate_rows是核心:它会同步拆分FORMAT和Sample列,保证每个字段与对应值一一对应,解决了不同行FORMAT字段不一致的问题。- 效率优势:结合
data.table的快速加载和tidyr的高效重塑,比vcfR的全量VCF解析快很多,只处理需要的字段。 - 后续扩展:如果Sample值包含逗号分隔的内容(如AD的参考/替代深度),可在解析完成后用
separate_wider_delim进一步拆分,比如:vcf_parsed <- vcf_parsed %>% separate_wider_delim(AD, delim = ",", names = c("AD_REF", "AD_ALT"))
内容的提问来源于stack exchange,提问作者milcs40
相关产品推荐
相关产品推荐

