2016-08-26 8 views
3

2つのファイルをマージして新しいファイルに割り当てたいのですが、 :awkは、列入力を修正して2つのファイルをマージし、出力ファイルに余分な列を追加します。

ファイル1:VDR.txtは、ヘッダーを持っていないスペースが分離され、次のようになります。

chr12-45000000-50000000 --- rs192072617 48225416 0.000 0.270 0.999 0 -1 -1 -1 
chr12-45000000-50000000 --- rs181728325 48225429 0.000 0.144 1.000 0 -1 -1 -1 
chr12-45000000-50000000 --- rs187216594 48225500 0.000 0.007 1.000 0 -1 -1 -1 

がファイル2:METAL1.tblは、ヘッダを持っているタブが分離され、このようになります:

MarkerName  Allele1 Allele2 Weight Zscore P-value Direction  HetISq HetChiSq  HetDf HetPVal 
rs192072617  a  g  2887.00 1.579 0.1143 ++  0.0  0.032 1  0.8579 
rs7929618  c  g  2887.00 -1.416 0.1568 -+  47.4 1.899 1  0.1681 
rs181728325  t  c  2887.00 1.469 0.1419 ++  73.9 3.830 1  0.05033 
rs7190157  a  c  2887.00 1.952 0.05088 +-  72.7 3.669 1  0.05542 
rs12364336  a  g  2887.00 -1.503 0.1328 -+  69.8 3.306 1  0.06902 
rs187216594  t  c  2887.00 -0.082 0.9349 +-  74.8 3.964 1  0.04649 
rs12562373  a  g  2887.00 -0.290 0.7717 -+  0.0  0.150 1  0.6984 

ファイルの行数が等しくない場合、最初のファイル(VDR.txt)は2番目のファイル(METAL1.tbl)よりもはるかに短くなります。

私がしたい:

  1. は、最初のファイル(VDR.txt)の3列と第二のファイル(METAL1.tbl)の第一列でこれらのファイルをマージします。
  2. 最初のファイル(VDR.txt)の列1,2,3および4と、2番目のファイル(METAL1.tbl)のすべての列のみを保持します。
  3. 最初のファイル(VDR.txt)の1列目からの最初のダッシュ "-"
  4. 前に文字だけが特定の文字列(例えば「VDR」)を繰り返し、出力ファイルに新しい列を追加してください
  5. 出力ファイルにはヘッダーは付いていませんが、必要な場合は以下のようにしておくといいでしょう。

だから私は最後に、このような出力ファイル(output.txtと)持っていると思います。それが得るん

$ awk 'FNR==NR {a[$1]=$1" "$2" "$3" "$4" "$5;next}{print $3, gensub(/-.*/, "", $1), $4, $2, a[$3]}' METAL1.tbl VDR.txt 

:これまで

gene MarkerName chr BP impute Allele1 Allele2 Weight Zscore P-value Direction HetISq HetChiSq HetDf HetPVal 
VDR rs192072617 chr12 48225416 --- a g 2887 1.579 0.1143 ++ 0 0.032 1 0.8579 
VDR rs181728325 chr12 48225429 --- t c 2887 1.469 0.1419 ++ 73.9 3.83 1 0.05033 
VDR rs187216594 chr12 48225500 --- t c 2887 -0.082 0.9349 +- 74.8 3.964 1 0.04649 

は私の試みをchr列と列は正しい方法で整列されますが、残念なことに、マージされたファイルではなく、VDR.txtから必要な列のみが出力されます。

これはかなり複雑な例であり、ご迷惑をおかけして申し訳ございませんが、ご了承ください。

おかげで、
メル

+2

だから、これを解決しようとする試みを行いましたか?もしそうなら、あなたはこれを共有すべきです。 「ここに私の仕様はありますか、私のためにコードしてください」という形式の質問は、一般的によく受け取られていませんが、「ここに私のコードがあります。 – Carpetsmoker

+0

ファイル内のフィールドはどのようにして識別されますか?固定幅ですか?またはデリミタは何ですか? –

+0

データサンプルを4列程度に減らすことをお勧めします(根本的な問題を解決するのに十分です)。あなたはunix/linuxコマンド 'join'について知っていますか?区切られたデータ( '|'やタブのようなもの)を扱うことができれば、おそらく1行にすることができます。しかし、私はあなたの入力と出力を慎重に見ていません(それはあまりにも広すぎるため、間違っている可能性があります)。がんばろう。 – shellter

答えて

2
$ cat > test.awk 
NR==FNR { 
    sub(/-.*/,"",$1)          # remove from 1st dash forward 
    a[$3]="VDR" OFS $3 OFS $1 OFS $4 OFS $2    # cols 1-4 of the 1st file 
    next           
} 
FNR==1 { 
    printf "%s", "H0" OFS "H3" OFS "H1" OFS "H4" OFS "H2" # 1st part of header 
} 
FNR==1 || $1 in a {          # header and matching rows 
    print a[$1], $0          # print'em 
} 
$ awk -f test.awk VDR.txt METAL1.tbl 
H0  H3  H1  H4  H2  MarkerName  Allele1 Allele2 Weight Zscore P-value Direction  HetISq HetChiSq  HetDf HetPVal 
VDR  rs192072617  chr12 48225416  ---  rs192072617  a  g2887.00 1.579 0.1143 ++  0.0  0.032 1  0.8579 
VDR  rs181728325  chr12 48225429  ---  rs181728325  t  c2887.00 1.469 0.1419 ++  73.9 3.830 1  0.05033 
VDR  rs187216594  chr12 48225500  ---  rs187216594  t  c2887.00 -0.082 0.9349 +-  74.8 3.964 1  0.04649 

awk 'NR==FNR { sub(/-.*/,"",$1); a[$3]="VDR" OFS $3 OFS $1 OFS $4 OFS $2; next} FNR==1 {printf "%s", "H0" OFS "H3" OFS "H1" OFS "H4" OFS "H2"} FNR==1 || $1 in a {print a[$1], $0}' VDR.txt METAL1.tbl 
+0

助けてくれてありがとうございます。これは素晴らしいですが、私はJonathan Lefflerのソリューションのようなワンライナーを探していました。 –

1

私はjoinコマンドを使用するには、2つのデータ・ファイルをソートしてきました - これは、出力内の行の順序に影響を与える - それが望ましくない場合、私は別のアプローチを使用することができます

export LANG=C 
genef=$1 
metalf=$2 
gene=$(basename $genef .txt) 
join -13 -21 <(sort -k3,3 $genef) <(sort -k1,1 $metalf)| 
awk -vgene=$gene ' 
{ 
    marker=$1 
    chr=substr($2, 1, index($2, "-")-1) 
    bp=$4 
    impute=$3 
    printf("%s\t%s\t%s\t%s\t%s", gene, marker, chr, bp, impute) 
    for(i=12; i<=NF; ++i) 
    printf("\t%s", $i) 
    printf("\n") 
} 
' 

これは、それは私は、限りタイトル行が必要とされていないとして、タブ区切りの出力

VDR  rs181728325  chr12 48225429  ---  t  c  2887.00 1.469 0.1419 ++  73.9 3.830 1  0.05033 
VDR  rs187216594  chr12 48225500  ---  t  c  2887.00 -0.082 0.9349 +-  74.8 3.964 1  0.04649 
VDR  rs192072617  chr12 48225416  ---  a  g  2887.00 1.579 0.1143 ++  0.0  0.032 1  0.8579 
+0

提案していただきありがとうございますが、私が 'join 'を好まなかったのは、ファイルを注文しなければならないということでした。これは最初のファイル(VDR.txt)では簡単な作業ですが、2番目のファイル(METAL1 .tbl)かなり大きい(〜600 Mb)ファイルです。 METAL1.tblをソートするだけでエラーが発生し、処理時間が増えたので、awkについての解決策を探していたのです。 –

+0

良い点 - 600MBのソートはかなり速いですが、awkを使ったシングルパスは常に良いです - ソートでどのようなエラーが見えますか? – pakistanprogrammerclub

3

ですシングル、かなり単純なawkスクリプトでストレートフォワード(S)

$ awk 'FNR == NR { sub(/-.*/, "", $1); row[$3] = "VDR " $3 " " $1 " " $4 " " $2 } 
>  FNR != NR { if ($1 in row) { name = $1; $1 = ""; print row[name] $0 } }' \ 
>  VDR.txt METAL1.tbl 
VDR rs192072617 chr12 48225416 --- a g 2887.00 1.579 0.1143 ++ 0.0 0.032 1 0.8579 
VDR rs181728325 chr12 48225429 --- t c 2887.00 1.469 0.1419 ++ 73.9 3.830 1 0.05033 
VDR rs187216594 chr12 48225500 --- t c 2887.00 -0.082 0.9349 +- 74.8 3.964 1 0.04649 
$ 

ファイルは、それを動作させるために示さ順にリストされなければなりません。

FNR == NR行が最初のファイルを処理します。subは最初のダッシュとその後ろのすべてを最初のフィールドで削除します。割り当ては$3のマーカー名でキー入力され、固定コード、マーカー名、縮小染色体番号、BP、および「Impute」と記されたダッシュのセットの行の開始に関する情報が含まれています。

FNR != NR行は、他のファイルを処理します。列1の値がrow配列のキーと一致する場合は、現在の行(開始位置が空白のまま$0になる)からキーを削除して、$0と連結したrowの値を出力します。

見出し行を特別に扱う必要はありません。値MarkerNameは最初のファイルの実際のマーカー名のいずれとも一致しないので、行は単に無視されます。ワンライナーとして

+0

と 'BEGIN {print" header}を追加してください} –

関連する問題