使用 awk 将多行合并为一行

使用 awk 将多行合并为一行

我正在处理一个非常大的数据集,格式如下:

chr1 45162 . . C T 
chr1 45162 . . C T
chr1 45162 A . . T
chr1 45162 . . C T
chr1 45257 A . . T
chr1 45257 A . . T
chr1 45413 A . . T
chr1 46844 A . C .
chr1 72434 A G . .
chr1 72434 A G . .
chr1 72434 A G . .
chr1 72434 A G . .
chr1 72515 A . C .
chr1 72515 A . . T
chr1 77689 A G . .    

我想要的输出是这样的:

chr1 45162 A . C T
chr1 45257 A . . T
chr1 45413 A . . T
chr1 46844 A . C .
chr1 72434 A G . .
chr1 72515 A . C T
chr1 77689 A G . .

本质上,对于第 2 列中的每个唯一值,我需要查看它具有的所有属性,这些属性可能存储在单独的行中。

所以,如果我有:

chr1 100 A . C .
chr1 100 . G . T

我希望输出中的行是:

chr1 100 A G C T

我有一个脚本,我相信它可以正常工作,但它太慢了。我认为必须有一种更简单的方法可以通过简单的awk脚本来完成此操作。

我当前的版本在这里:http://ideone.com/e.js/ETBRz3 但是,就像我说的,我认为应该有一个几乎 1 衬垫版本可能仅使用awk.

欢迎所有建议。

(如果它可以简化事情,我可以返回并修改生成此文件的脚本,使空字段是空字符串而不是“.”字符。)

答案1

这是一种方法:

$ awk '$2!=old && NR>1 {for (i=1;i<=NF;i++) printf a[old","i]" "; print"";} {old=$2;for (i=1;i<=NF;i++) {if (a[$2","i]=="." ||  a[$2","i]=="") a[$2","i]= $i}} END{for (i=1;i<=NF;i++) printf a[old","i]" "; print"";}' file 
chr1 45162 A . C T 
chr1 45257 A . . T 
chr1 45413 A . . T 
chr1 46844 A . C . 
chr1 72434 A G . . 
chr1 72515 A . C T 
chr1 77689 A G . . 

怎么运行的

  • $2!=old && NR>1 {for (i=1;i<=NF;i++) printf a[old","i]" "; print"";}

    在第一行之后,每当我们遇到第二列的新值时,就打印出前一个值的结果。

  • old=$2;for (i=1;i<=NF;i++) {if (a[$2","i]=="." || a[$2","i]=="") a[$2","i]= $i}

    a使用当前行的值更新数组。

    GNUawk有很好的二维数组。然而,为了兼容性,我使用 POSIX 兼容的替代品。

  • END{for (i=1;i<=NF;i++) printf a[old","i]" "; print"";}

    最后一行之后,打印出最后部分的信息。

答案2

未排序行的另一种变体:

awk '{
k[$2]=$1;
for(i=3;i<7;i++){
  if(l[$2,i]=="." || l[$2,i]=="")
    l[$2,i]=$i;
  }
}
END{
for(n in k){
  printf("%s %s ",k[n],n);
  for(m=3;m<7;m++)
    printf("%s ", l[n,m]);
  print "";
  }
 }' file

简短的解释:

通过文件脚本创建两个关联数组:kwith field#2as index 和lwith index field#2,Next_fields_number。当文件中的所有行都通过时,脚本启动两个循环来打印第一个数组和第二个数组中的字段。

答案3

一个perl办法:

$ perl -anle '
  for (2..$#F) {
    $h{join(" ",@F[0..1])}->{$_} ||= $F[$_];
    $h{join(" ",@F[0..1])}->{$_} = $F[$_] if $F[$_] ne ".";
  }
  END { print "$_ @{$h{$_}}{sort keys %{$h{$_}}}" for sort keys %h }
' file
chr1 45162 A . C T
chr1 45257 A . . T
chr1 45413 A . . T
chr1 46844 A . C .
chr1 72434 A G . .
chr1 72515 A . C T
chr1 77689 A G . .

相关内容