2つのファイルがあります。ファイル1の列1はファイル2の列2に置き換える必要があり、ファイル1の列2,3,4-5または5-4(クロスマッチ)は列1,4,5と一致します。 -6またはファイル2の6-5。
ファイル1
SNP Chr Pos EA NEA EAF Beta SE Pvalue Neff
1:79137 1 79137 A T 0.25 -0.026 0.0073 4.0e-04 231420
1:79033 1 79033 A G 0.0047 -0.038 0.056 4.9e-01 225429
1:118630 1 118630 C T 0.99 -0.033 0.055 5.5e-01 226311
1:533179 1 533179 A G 1 -0.098 0.19 6.1e-01 185906
ファイル2
1 1:79033_A_G 0 79033 A G
1 1:79137_A_T 0 79137 T A
1 1:118630_C_T 0 118630 T C
1 1:533179_A_G 0 533179 G A
次の出力が必要です。
SNP Chr Pos EA NEA EAF Beta SE Pvalue Neff
1:79137_A_T 1 79137 A T 0.25 -0.026 0.0073 4.0e-04 231420
1:79033_A_G 1 79033 A G 0.0047 -0.038 0.056 4.9e-01 225429
1:118630_C_T 1 118630 C T 0.99 -0.033 0.055 5.5e-01 226311
1:533179_A_G 1 533179 A G 1 -0.098 0.19 6.1e-01 185906
ファイルに正確な行がないため、ファイルはタブで区切られません。以下のコードを試しましたが、うまくいきません。コードを修正してもらえますか?
awk 'NR==FNR{chr[$1]=$1;snp[$2]=$2;pos[$4]=$4;a1[$5]=$5;a2[$6]=$6;next} ($1 in chr)&&($4 in pos)&& ((($5 in a1) && ($6 in a2)) || (($6 in a1) && ($5 in a2))) {$2==snp[$2]}' file 2 file1
編集1:
次のPerlコードはいくつかのエラーを引き起こし、約20,000の重複行を生成します。
ファイル1
SNP Chr Pos EA NEA EAF Beta SE Pvalue Neff
7:10100610 7 10100610 A G 0.0002 0.13 0.58 8.2e-01 120658
7:10100610 7 10100610 C G 0.0013 0.1 0.13 4.4e-01 139170
10:1006107 10 1006107 C G 1 -0.11 0.42 7.9e-01 152016
ファイル2
7 7:10100610_G_A 0 10100610 A G
7 7:10100610_G_C 0 10100610 C G
10 10:1006107_C_G 0 1006107 G C
次の行の推定出力は次のとおりです。
7:10100610_G_A 7 10100610 A G 0.0002 0.13 0.58 8.2e-01 120658
7:10100610_G_C 7 10100610 C G 0.0013 0.1 0.13 4.4e-01 139170
10:1006107_C_G 10 1006107 C G 1 -0.11 0.42 7.9e-01 152016
しかし、Perlコードは出力を提供します。
7:10100610_G_A 7 10100610 A G 0.0002 0.13 0.58 8.2e-01 120658
10:1006107_C_G 7 10100610 C G 0.0013 0.1 0.13 4.4e-01 139170
10:1006107_C_G 10 1006107 C G 1 -0.11 0.42 7.9e-01 152016
答え1
このjoin
コマンドは、複数のファイルで一致する行をリンクする操作を実行します。ただし、入力ファイルにはいくつかの要件があるため、プロセス中にいくつかの一時ファイルといくつかの追加フィールドを作成する必要があります。
awk '{printf $2" "$3" "$4" "$5"%"$1"%"; $1="";print $0 "%" NR }' < file1 | sort > 1.tmp
awk '{print $1" "$4" "$5" "$6"%"$2} $5 != $6 {print $1" "$4" "$6" "$5"%"$2}' < file2 | sort > 2.tmp
join -a 1 -t % -o 1.4 2.2 1.2 1.3 1.tmp 2.tmp | sort -t % -n | awk -F % '!$2{$2=$3}{print $2" "$4}'
段階的に
最初のファイルを前処理します。
awk '{printf $2" "$3" "$4" "$5"%"$1"%"; $1="";print $0 "%" NR }''
出力例:
1 118630 C T%1:118630% 1 118630 C T 0.99 -0.033 0.055 5.5e-01 226311%4
この 4 つのフィールドは%
次のように区別されます。
- 一致する必要がある「キー」(入力フィールド2-5)
- 元の最初の列(一致する項目がない場合は必須)
- 元の行の残りの部分
- 元の行番号(後でファイルの順序を復元できるように
sort
)
この出力は入力をソートする必要があるため、一時ファイルsort
にパイプされます。join
2番目のファイルの場合:
awk '{print $1" "$4" "$5" "$6"%"$2} $5 != $6 {print $1" "$4" "$6" "$5"%"$2}'
出力例:
1 118630 C T%1:118630_C_T
1 118630 T C%1:118630_C_T
フィールド5と6が一致するように指定すると、2行目が印刷され、互いに置き換えられます(同じでない場合)。ここで - で区切られたフィールド%
は次のとおりです。
- 「キー」と一致する必要があります
- 2列
今回も出力はsort
別の一時ファイルにパイプされます。
その後、主な「参加」ステップが続きます。
join -a 1 -t % -o 1.4 2.2 1.2 1.3 1.tmp 2.tmp
2番目のグループに一致するものがない場合は、 -a 1
最初のグループの行を保持するように指示します。区切り文字を(スペースの代わりに)に設定します。このパラメーターは、次の4つの出力フィールドを生成します。join
-t %
%
-o
- ファイル1、列4:行番号
- ファイル2、列2:代替場所
file2
(一致するものがない場合は空) - ファイル1、列2:元の列1
file1
- ファイル1、列3:行の残りの部分は
file1
サンプル出力ライン:
4%1:118630_C_T%1:118630% 1 118630 C T 0.99 -0.033 0.055 5.5e-01 226311
その後、sort
元のファイルの順序を復元できます(数値ソート、フィールド区切り文字%
)。
sort -t % -n
最後に、awk
「交換」フィールドが空であることを確認し(一致する項目がないため)、空の場合は元の列1を使用します。また、行番号とすべてを捨てます%
。
awk -F % '!$2{$2=$3}{print $2" "$4}'
最終出力ライン:
1:118630_C_T 1 118630 C T 0.99 -0.033 0.055 5.5e-01 226311
答え2
私はPerlでこれをします。 Perlには、andを同じものとしてsort
簡単に処理できる機能があるからです。たとえば、すべてのサンプルファイルの出力を組み合わせて表示します。A T
T A
$ perl -lane 'if(!$k){$name{join("","chr".$F[0],$F[3],sort($F[4],$F[5]))}=$F[1]; }else{$var=join("", "chr".$F[1],$F[2],sort($F[3],$F[4])); $F[0]=$name{$var} if $name{$var};print join "\t", @F; } $k++ if eof' file2 file1
SNP Chr Pos EA NEA EAF Beta SE Pvalue Neff
7:10100610_G_A 7 10100610 A G 0.0002 0.13 0.58 8.2e-01 120658
7:10100610_G_C 7 10100610 C G 0.0013 0.1 0.13 4.4e-01 139170
10:1006107_C_G 10 1006107 C G 1 -0.11 0.42 7.9e-01 152016
1:79137_A_T 1 79137 A T 0.25 -0.026 0.0073 4.0e-04 231420
1:79033_A_G 1 79033 A G 0.0047 -0.038 0.056 4.9e-01 225429
1:118630_C_T 1 118630 C T 0.99 -0.033 0.055 5.5e-01 226311
1:533179_A_G 1 533179 A G 1 -0.098 0.19 6.1e-01 185906
または少し明確です。
$ perl -lane 'if(!$k){
$name{join("","chr".$F[0],$F[3],sort($F[4],$F[5]))}=$F[1];
}
else{
$var=join("", "chr".$F[1],$F[2],sort($F[3],$F[4]));
$F[0]=$name{$var} if $name{$var};
print join "\t", @F;
}
$k++ if eof' file2 file1
SNP Chr Pos EA NEA EAF Beta SE Pvalue Neff
7:10100610_G_A 7 10100610 A G 0.0002 0.13 0.58 8.2e-01 120658
7:10100610_G_C 7 10100610 C G 0.0013 0.1 0.13 4.4e-01 139170
10:1006107_C_G 10 1006107 C G 1 -0.11 0.42 7.9e-01 152016
1:79137_A_T 1 79137 A T 0.25 -0.026 0.0073 4.0e-04 231420
1:79033_A_G 1 79033 A G 0.0047 -0.038 0.056 4.9e-01 225429
説明する
perl -lane
:これは-a
Perlをawkのように動作させ、自動的に入力を空白の配列に分割します@F
。 Perl配列は最初のフィールドで始まる0
ので、2番目のフィールドになります。フィールドNはです。 Perlは引数をテキストファイルとして読み込み、与えられたスクリプトを各行に適用します。各行から末尾の改行を削除し、各呼び出しに改行を追加するだけです。$F[0]
$F[1]
$F[N-1]
-n
-e
-l
print
$k++ if eof
$k
:ファイルの終わり(eof
)に達すると、変数は1増加します。その後、if(!$k)
($ kが定義されていない場合)、NR==FNR
awkで同等のものとして使用できます。if(!$k){$name{join("","chr".$F[0],$F[3],sort($F[4],$F[5]))}=$F [1];}
: if this is the first file,
file2, join fields 1, 4, and the sorted fields 5 and 6, into a string and use that string as the key in the hash (associative array)
name. Then, save the variant's name from file2 as the value associated with that key. The sorting lets us treat
ATand
TA 「as equivalent. I use
chrto deal with cases like
」and
else{
:今2番目のファイルを読んでいる場合file1
。$var=join("", $F[1],$F[2],sort($F[3],$F[4]));
:ビルドキー。今回は、フィールド2、3を使用して4と5を並べ替えます。$F[0]=$name{$var} if $name{$var};
name
:キーに値がある場合、最初のフィールドをハッシュに格納された値に設定します。ヘッダーや存在するが存在しない他のバリアントをif
変更しないでください。file1
file2
print join "\t", @F;
:上記で行った変更を含むフィールドを印刷します。