2つの列の一致に基づいて2つのファイルをマージする方法は?


33

私はfile1が好きです:

0   AFFX-SNP-000541  NA
0   AFFX-SNP-002255  NA
1   rs12103          0.6401
1   rs12103_1247494  0.696
1   rs12142199       0.7672

そしてfile2:

0   AFFX-SNP-000541   1
0   AFFX-SNP-002255   1
1   rs12103           0.5596
1   rs12103_1247494   0.5581
1   rs12142199        0.4931

そして、次のようなfile3が必要です:

0   AFFX-SNP-000541     NA       1
0   AFFX-SNP-002255     NA       1
1   rs12103             0.6401   0.5596
1   rs12103_1247494     0.696    0.5581
1   rs12142199          0.7672   0.4931

つまり、file2の4番目の列を2番目の列の名前でfile1に配置します。


1
File2には3列しかありませんか?
ベルンハルト14

回答:


48

これはそれを行う必要があります:

join -j 2 -o 1.1,1.2,1.3,2.3 file1 file2

重要:これは、SNP名に従ってファイルが(例のように)ソートされていることを前提としています。そうでない場合は、最初に並べ替えます。

join -j 2 -o 1.1,1.2,1.3,2.3 <(sort -k2 file1) <(sort -k2 file2)

出力:

0 AFFX-SNP-000541 NA 1
0 AFFX-SNP-002255 NA 1
1 rs12103 0.6401 0.5596
1 rs12103_1247494 0.696 0.5581
1 rs12142199 0.7672 0.4931

説明(からinfo join):

`join 'は、同一の結合フィールドを持つ入力行のペアごとに1行を標準出力に書き込みます。

`-1 FIELD'
     Join on field FIELD (a positive integer) of file 1.

`-2 FIELD'
     Join on field FIELD (a positive integer) of file 2.

`-j FIELD'
     Equivalent to `-1 FIELD -2 FIELD'.

`-o FIELD-LIST'

 Otherwise, construct each output line according to the format in
 FIELD-LIST.  Each element in FIELD-LIST is either the single
 character `0' or has the form M.N where the file number, M, is `1'
 or `2' and N is a positive field number.

したがって、上記のコマンドは2番目のフィールドでファイルを結合し、ファイル1の1番目、2番目、3番目のフィールドを出力し、その後にfile2の3番目のフィールドを出力します。


16

以下を使用できますawk

$ awk 'NR==FNR {h[$2] = $3; next} {print $1,$2,$3,h[$2]}' file2 file1 > file3

出力:

$ cat file3
0 AFFX-SNP-000541 NA 1
0 AFFX-SNP-002255 NA 1
1 rs12103 0.6401 0.5596
1 rs12103_1247494 0.696 0.5581
1 rs12142199 0.7672 0.4931

説明:

ウォークスルーfile2NR==FNR最初のファイル引数にのみ当てはまります)。列2をキーとして使用して、列3をハッシュ配列に保存しますh[$2] = $3。次に、file13つの列すべてをウォークスルーして出力し$1,$2,$3、対応する保存列をhash-arrayから追加しますh[$2]


どうもありがとう。「h [$ 2] = $ 3」とはどういう意味ですか?実際、複雑なケースではfile1 $ 2 == file2 $ 2を正確に一致させる必要があります(同じ順序である必要はありません)。
大東張14

1
h[$2] = $3ハッシュ割り当てです。$3値および$2キーとして保存します。例:h["name"] = "Dadong"。今、print h["name"]出力しますDadong。必要なことを行い、両方のファイルの2番目の列に正確に一致します。
グレブネケ14

6

順序付けが必要ない場合、単純な解決策は

paste file{1,2} | awk '{print $1,$2,$3,$6}' > file3

これは、すべての行に3つのエントリがあり、両方のファイルの列1と2が同じであると仮定しています(サンプルデータのように)


1
偉大な使用のための1paste
grebneke

1
@grebnekeとBernhard、あなたはファンのようですが、coreutilsでこれpasteに答える方法を見つけられますか?
テルドン


1
@terdonこのs ***を出力しているプログラムを再考することをお勧めします
Bernhard 14

フォーマットに問題はなく、完全に適切なタブ区切りファイルです。いずれにせよ、この種のデータでは、通常、フォーマットに関して選択の余地がなく、別のプログラムから出力されます。
テルドン
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.