【问题标题】:using awk to exclude a range of rows from one file depeding on second file使用 awk 根据第二个文件从一个文件中排除一系列行
【发布时间】:2021-02-23 09:06:42
【问题描述】:

我有两个文件 - 第一个文件在第 1 列中包含一个数字 (1-22) 以及一个从较低数字(第 2 列)到较高数字(第 3 列)的范围。这是前几行:

1 11362778 12362778
1 22054176 23054176
1 28191734 29191734
1 42956767 43956767
1 65941329 66941329

第一个文件没有任何标题。

在第二个文件中,我有很多列,第一个显示在这里:

SNP CHR BP
rs115828134 1 11363041
rs2788537 1 11363231
rs12141932 1 11363301

如果文件 2 中的第 2 列等于文件 1 中的第 1 列并且如果文件 2 中的第 3 列在文件 2 中的第 2 列和第 3 列的范围内,我想要做的是删除文件 2 中的所有行。

基本上是这样的:,但循环遍历文件 1 的所有行。

awk '{if($2==1 && $3 < 11362778 || $3 > 12362778) print $0}' file 2 > results.txt 

【问题讨论】:

    标签: awk


    【解决方案1】:

    我 100% 同意 @jared_mamrot,为此使用适当的生物信息工具。

    然而,有一种方法可以使用 awk 来解决这个问题。但是,在依赖它进行严肃的科学之前,请务必在真实数据集上进行测试,因为我不完全确定它是否涵盖所有极端情况,尤其是您的有限示例。

    数据(添加匹配数据):

    $ cat file1
    1       11362778        12362778
    1       22054176        23054176
    1       28191734        29191734
    1       42956767        43956767
    1       65941329        66941329
    2       42956767        43956767
    2       65941329        66941329
    
    $ cat file2
    SNP     CHR     BP
    rs10875231      1       100000012
    rs6678176       1       100000827
    rs78286437      1       100000843
    rr234233        1       29000000
    rr453654        1       29000120
    e34534534       1       23444444
    rs144406489     1       100001138
    rr564564        2       29000120
    e34534534       2       23444444
    rs144406489     2       42956775 
    

    用途:

    $ awk 'NR==FNR{ chr[NR]=$1; x[NR]=$2; y[NR]=$3; en=NR }
           NR!=FNR{ set=0;
                    for(i=1;i<=en;i++){
                      if(chr[i]==$2 && ( $3 <= y[i] && $3 >= x[i] ) ){
                        set=0; break
                      }
                      else{ set=1 }
                    }
                    if(set==1){ print }
          }' file1 file2
    

    输出:

    SNP     CHR     BP
    rs10875231      1       100000012
    rs6678176       1       100000827
    rs78286437      1       100000843
    e34534534       1       23444444
    rs144406489     1       100001138
    rr564564        2       29000120
    e34534534       2       23444444 
    

    【讨论】:

      【解决方案2】:

      这类特定领域的问题更适合https://bioinformatics.stackexchange.com/

      话虽如此,一种可能的解决方案是将第二个文件转换为床格式(与文件 1 相同),然后使用bedtools 来识别和排除匹配项。

      首先,将file_1中的第一行改成坐标对应file_2中的一个条目,否则看不到方法是否有效:

      文件_1.bed:

      1   100000011   100000014
      1   22054176    23054176
      1   28191734    29191734
      1   42956767    43956767
      1   65941329    66941329
      

      文件_2.bed

      # generated using
      # awk 'NR>1 {print $2 "\t" $3 "\t" $3 "\t" $1}' file_2 > file_2.bed
      1   100000012   100000012   rs10875231
      1   100000827   100000827   rs6678176
      1   100000843   100000843   rs78286437
      1   100001138   100001138   rs144406489
      

      使用bedtools intersect 识别和删除相交的条目:

      bedtools intersect -v -a file_2.bed -b file_1.bed
      

      输出:

      1   100000827   100000827   rs6678176
      1   100000843   100000843   rs78286437
      1   100001138   100001138   rs144406489
      

      【讨论】:

      • 谢谢!是的-bedtools 工作,只是希望能够将其编写为 awk
      【解决方案3】:

      这样的东西应该可以工作,但你没有可测试的输入,所以没有测试(范围没有重叠!)。

      $ awk 'NR==FNR {c[$1]++; b[$1,c[$1]]=$2; e[$1,c[$1]]=$3; next}
             $2 in c {for(i=1;i<=c[$2];i++) 
                        if(b[$2,i]<$3 && $3<e[$2,i]) next}1' file1 file2
      

      还请发布示例输入,以便可以复制/粘贴以方便测试。

      使用来自@AndreWildberg 的回答和管道到column 的示例输入给出

      $ awk ... | column -t
      
      SNP          CHR  BP
      rs10875231   1    100000012
      rs6678176    1    100000827
      rs78286437   1    100000843
      e34534534    1    23444444
      rs144406489  1    100001138
      rr564564     2    29000120
      e34534534    2    23444444
      

      请注意,这应该比替代方法稍微快一些,因为扫描重叠部分仅限于匹配代码。根据您的输入大小,它可能可以忽略不计。

      【讨论】:

      • 谢谢 - 它看起来与想要的相反 - 即它打印了我想要删除的所有行。我已经更新了上面的文件 2
      • 我想要的是一个省略文件 1 区域的文件
      • 好吧,我误会了。现在更新为跳过而不是打印。
      猜你喜欢
      • 2018-12-15
      • 1970-01-01
      • 2020-02-25
      • 2019-01-04
      • 1970-01-01
      • 2014-05-24
      • 1970-01-01
      • 1970-01-01
      • 2023-03-10
      相关资源
      最近更新 更多