如何移除TSV文件中基因组坐标重复超过指定次数的行?
解决TSV文件前3列重复行过滤问题
我明白你要做的是:从TSV文件里移除前3列(chr、position、position2)重复次数超过指定值(比如3或4次)的行,只保留每组重复行的前n次出现。下面我给你详细的解决方案,先看示例和问题分析,再给正确命令。
示例文件说明
输入文件 file.tsv
chr1 100 101 geneA exp1 chr1 100 101 geneA exp2 chr1 100 101 geneA exp3 chr1 100 101 geneA exp4 chr2 200 201 geneB exp1 chr2 200 201 geneB exp2 chr3 300 301 geneC exp1
n=3时的期望输出
只保留前3列重复次数≤3的所有行,对于重复4次的chr1组,只留前3行:
chr1 100 101 geneA exp1 chr1 100 101 geneA exp2 chr1 100 101 geneA exp3 chr2 200 201 geneB exp1 chr2 200 201 geneB exp2 chr3 300 301 geneC exp1
你之前命令的问题分析
你用的awk '{if(!seen[$1,$2,$3]++) {if(++count[$1,$2,$3]<=3) print} }'逻辑有问题:!seen[$1,$2,$3]++只有当该组第一次出现时才为真,后面的所有重复行都会跳过这个判断,所以最终只会打印每组的第一行,完全达不到保留前n次重复行的效果。
而sort+uniq的组合默认只能实现去重或者统计重复次数,没法直接保留每组的前n行,所以也不符合需求。
正确解决方案
方案1:保持原文件的行顺序(推荐)
这个方案用awk两次遍历文件:第一次统计每组前3列的重复次数,第二次遍历输出符合条件的行(总次数≤n则全输出,否则只输出前n次)。
命令如下(把n=3改成n=4就能适配4次的需求):
awk -v n=3 'BEGIN{FS=OFS="\t"} NR==FNR{count[$1,$2,$3]++; next} count[$1,$2,$3]<=n || --count[$1,$2,$3]>=0' file.tsv file.tsv
逻辑解释:
BEGIN{FS=OFS="\t"}:指定输入输出的分隔符为制表符,适配TSV格式NR==FNR:第一次遍历文件时,统计每个前3列组合的出现次数,存到count数组- 第二次遍历时:
- 如果该组合的总次数≤n,直接输出所有行
- 如果总次数>n,每输出一行就把
count减1,直到count小于0就停止输出该组合的行
方案2:不介意行顺序的情况(更快处理大文件)
如果不需要保留原文件的行顺序,可以先按前3列排序,再用awk保留每组的前n行:
sort -k1,3 file.tsv | awk -v n=3 'BEGIN{FS=OFS="\t"} $1$2$3 != prev {cnt=0; prev=$1$2$3} cnt++ < n'
逻辑解释:
sort -k1,3 file.tsv:按第1到3列排序,把相同的前3列组合集中到一起- awk部分:跟踪前一个组合的标识
prev,遇到新组合就重置计数器cnt,计数器小于n时就打印当前行
这两个方案都能完美实现你的需求,你可以根据是否需要保留原顺序来选择。
内容的提问来源于stack exchange,提问作者avonlea891
相关产品推荐
相关产品推荐

