awkを使用して複数行を1つにまとめる

awkを使用して複数行を1つにまとめる

私は次の形式の非常に大きなデータセットで作業しています。

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 しかし、私が言ったようにawk

すべての提案を歓迎します。

(単純化している場合は、空のフィールドが「.」文字ではなく空の文字列になるようにこのファイルを生成するスクリプトを変更して変更できます。)

ベストアンサー1

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"";}

    1 行目以降の 2 列目の新しい値に出会うたびに、前の値の結果を出力します。

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

    a現在行の値で配列を更新します。

    GNUにはawk素晴らしい2次元配列があります。ただし、互換性の理由からPOSIX準拠の代替方法を使用します。

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

    最後の行の後に情報の最後の部分を印刷します。

おすすめ記事