2つの共通列に基づいて2つのテーブルを結合し、一致しない場合はNAまたはNull値を追加します。

2つの共通列に基づいて2つのテーブルを結合し、一致しない場合はNAまたはNull値を追加します。

このように2つのテーブルをマージしたい

1番テーブル

Chr1 5
Chr1 10
Chr1 20
Chr2 10
Chr2 30

表2

Chr1 10 value value2
Chr1 20 value value2
Chr2 30 value value2

希望の出力

Chr1 5
Chr1 10 value value2
Chr1 20 value value2
Chr2 10
Chr2 30 value value2

2つのテーブルの2つの列に一致する行のみを保持するテーブルをマージするために、awkでスクリプトを見つけました。ただし、ここではTable_1のすべての行が必要ですが、一致する場合はTable_2の値を追加します。これを達成する方法を教えてもらえますか?

答え1

$ awk '{ key = $1 FS $2 };
       NR == FNR { t[key] = $0; next };
       key in t { print t[key]; next };
       1' table2.txt table1.txt
Chr1 5
Chr1 10 value value2
Chr1 20 value value2
Chr2 10
Chr2 30 value value2
  • 読み取った各入力行では、(読み取った両方のファイルに対して)変数は最初の2つのフィールドkey$1および$2)に設定され、その間にはフィールド区切り文字(FS)があります。 FS両方のフィールドに含まれないことが保証される唯一の文字であるため、一意のキーを生成することが保証される唯一の文字であるために使用されます。キーは、関連配列のインデックスとして使用されますt

  • table2.txt読むとき(〜しなければならないコマンドラインの最初のファイル名引数としてリストされています)、各入力行は配列の1つの要素に格納されますt

    重複した項目が含まれている場合にのみ記憶されますtable2.txt。つまり、最初の2つのフィールドが同じ複数行を持つ場合です。最後一つは見る。これらのすべての重複項目(表示される順序で)を覚えている場合は、awkスクリプトの2行目を次のように変更してください。

     NR == FNR { if (key in t) { t[key] = t[key] "\n" $0 } else { t[key] = $0 }; next };
    
  • 最初のファイルの読み取りが終了したらtable1.txt(2番目のファイル名arg)を読み取り、配列に対応するエントリがある場合は印刷しtable2、それ以外の場合は現在の行を印刷します。

  • 1スクリプトの最後の行はawkawkの慣用的な略語です{print}。値が1true と評価され、一部の値が true と評価された場合、デフォルトのアクションは現在の行を印刷することです。

メモ:table2.txt容量が大きいとRAMが大量に使用されます。これは、ギガバイトのRAMを備えた最新のシステムでは問題にはなりません。

答え2

$ awk '{k=$1 FS $2} NR==FNR{map[k]=$0; next} {print (k in map ? map[k] : $0)}' table2 table1
Chr1 5
Chr1 10 value value2
Chr1 20 value value2
Chr2 10
Chr2 30 value value2

関連情報