如何用R或Bash提取SNP数据框的参考与替代等位基因信息
刚好处理过类似的基因型拆分需求,给你两个靠谱的方案,R和Bash都有,按需选就行:
R 解决方案
不管你用 tidyverse 还是基础R,都能快速搞定这个拆分:
用 tidyverse(推荐,代码更易读)
- 先加载工具包:
library(tidyverse)
- 先把你给的示例数据导进来(实际用的时候替换成你的真实数据框就行):
df <- structure(list(`c("12545=1", "12545=0")` = c("12545=1|1", "12545=0|0" ), `c("12994=0|0", "12994=0|1")` = c("12994=0|0", "12994=0|1" ), `c("15240=0|0", "15240=1|1")` = c("15240=0|0", "15240=1|1" )), row.names = c(NA, -2L), class = c("tbl_df", "tbl", "data.frame" ))
- 提取参考等位基因(|前的数值):
ref_df <- df %>% mutate(across(everything(), ~ str_extract(., "(?<=\\=)\\d(?=\\|)") %>% as.integer()))
这里的正则表达式专门匹配=之后、|之前的单个数字,转成整数后就得到纯0/1的矩阵。
- 提取替代等位基因(|后的数值):
alt_df <- df %>% mutate(across(everything(), ~ str_extract(., "(?<=\\|)\\d") %>% as.integer()))
这个正则则是抓|之后的单个数字,同样转成整数类型。
用基础R(不用额外装包)
如果不想加载tidyverse,用base R的lapply和正则替换也能实现:
# 拆分参考等位基因 ref_df_base <- data.frame(lapply(df, function(x) as.integer(sub(".*=(\\d)\\|.*", "\\1", x)))) # 拆分替代等位基因 alt_df_base <- data.frame(lapply(df, function(x) as.integer(sub(".*\\|(\\d)", "\\1", x))))
这里的sub函数会把每个单元格里的内容替换成我们需要的捕获组(括号里的数字),再转成整数。
Bash 解决方案
如果你的数据是存成文本文件(比如TSV格式,制表符分隔),用命令行工具处理会更快,尤其是大数据量的时候:
提取参考等位基因
假设你的原始数据存在genotypes.txt里,运行下面的命令会生成只含参考等位基因的文件ref_genotypes.txt:
awk -F'\t' '{for(i=1;i<=NF;i++){sub(/.*=/,"",$i); sub(/\|.*/,"",$i);} print $0}' genotypes.txt > ref_genotypes.txt
解释:按制表符拆分每一列,先删掉=及之前的所有内容,再删掉|及之后的内容,最后输出处理后的行。
提取替代等位基因
同样,生成替代等位基因的文件alt_genotypes.txt:
awk -F'\t' '{for(i=1;i<=NF;i++){sub(/.*\|/,"",$i); sub(/.*=/,"",$i);} print $0}' genotypes.txt > alt_genotypes.txt
解释:先删掉|及之前的内容,再清理掉可能残留的=及前面的内容,只留下|后的数字。
如果你更习惯用sed,也可以用更简洁的正则:
# 提取参考等位基因 sed -E 's/.*=([01])\|.*/\1/g' genotypes.txt > ref_genotypes.txt # 提取替代等位基因 sed -E 's/.*\|([01])/\1/g' genotypes.txt > alt_genotypes.txt
这个命令直接用捕获组提取0或1,替换整个单元格的内容,效率很高。
内容的提问来源于stack exchange,提问作者Darren




