如果基于第一列有一定数量的观察,如何保留行?

如果基于第一列有一定数量的观察,如何保留行?

我有一个类似于下面示例的文件。第一列是 SNP id。

head data
2L:647803 1 2 44.31655 -12.2373
2L:647803 1 2 43.63717 -12.302
2L:647803 1 2 43.80007 -12.3451
2L:2602906 1 2 43.39748 -11.4894
2L:2602906 1 2 44.43951 -12.3093
2L:2602906 1 2 43.80007 -12.3451
2L:3146785 1 2 44.31655 -12.2373
2L:3146785 1 2 44.43951 -12.3093
2L:3146785 1 2 43.80007 -12.3451
2L:3771395 1 2 43.39748 -11.4894
2L:3771395 1 2 43.2661 -11.6803
2L:3945568 1 2 43.63717 -12.302
2L:3945568 1 2 43.39032 -11.6099

对于每个 SNP ( 2L:647803, 2L:2602906, 2L:3146785, ...),我想要 3 行。如果每个 SNP 没有 3 行,我想删除该 SNP。这是我想要的输出:(2L:3771395并且 2L:3945568被删除,因为每个输出只有两个实例)。

head desired
2L:647803 1 2 44.31655 -12.2373
2L:647803 1 2 43.63717 -12.302
2L:647803 1 2 43.80007 -12.3451
2L:2602906 1 2 43.39748 -11.4894
2L:2602906 1 2 44.43951 -12.3093
2L:2602906 1 2 43.80007 -12.3451
2L:3146785 1 2 44.31655 -12.2373
2L:3146785 1 2 44.43951 -12.3093
2L:3146785 1 2 43.80007 -12.3451

答案1

不优雅但实用:

$ awk 'NR==FNR {a[$1]++; next} a[$1]==3' data data
2L:647803 1 2 44.31655 -12.2373
2L:647803 1 2 43.63717 -12.302
2L:647803 1 2 43.80007 -12.3451
2L:2602906 1 2 43.39748 -11.4894
2L:2602906 1 2 44.43951 -12.3093
2L:2602906 1 2 43.80007 -12.3451
2L:3146785 1 2 44.31655 -12.2373
2L:3146785 1 2 44.43951 -12.3093
2L:3146785 1 2 43.80007 -12.3451

答案2

使用米勒(https://github.com/johnkerl/miller)并运行

mlr --nidx count-similar -g 1 then filter '$count==3' then cut -x -f count inputfile

你有

2L:647803 1 2 44.31655 -12.2373
2L:647803 1 2 43.63717 -12.302
2L:647803 1 2 43.80007 -12.3451
2L:2602906 1 2 43.39748 -11.4894
2L:2602906 1 2 44.43951 -12.3093
2L:2602906 1 2 43.80007 -12.3451
2L:3146785 1 2 44.31655 -12.2373
2L:3146785 1 2 44.43951 -12.3093
2L:3146785 1 2 43.80007 -12.3451
  • mlr --nidx count-similar -g 1计算不同字段 1 的值
  • then filter '$count==3'仅过滤此计数 = 3 的行
  • then cut -x -f count删除计数列

答案3

这是另一个awk(只不过是awk)解决方案。

  • 它假设输入是按“SNP id”整理的;即,所有 SNP id = 647 的行将在一起。
  • 它不假设输入已排序;即,SNP id 647 可以出现在 2602 之前或之后。
  • 它只对数据进行一次传递。
  • 它不会输出出现超过 3 次的 SNP id 的任何数据。
awk '
  {
    if ($1 == last) {
        count++
        if (count <= 3) line[count] = $0
    } else {
        if (count == 3) { print line[1]; print line[2]; print line[3]; }
        last = $1
        count = 1
        line[count] = $0
    }
  }
END {   if (count == 3) { print line[1]; print line[2]; print line[3]; } }
  '

它只是计算第一个字段/列 ( ) 中具有相同值的连续行,$1并保存具有相同值的行。如果它遇到一个新值(或输入的末尾),那么,如果前一个值出现了三次,它会打印出保存的行。

相关内容