互いに隣接する染色体に基づいてソートされたファイルデータのマージ - カラム万力

互いに隣接する染色体に基づいてソートされたファイルデータのマージ - カラム万力

chr position value 形式のファイルが複数あります。

「chr」、「position」、「samp1」、「samp2」、「samp3」、「samp4」の形式に変換したいと思います。

たとえば、

サンプル1:

chr position value
1   3774318 1
1   3774319 1
1   3775200 2
1   3775201 7
1   3775202 70
1   3775203 7
1   3775204 270
1   3775205 3
1   3775206 5

サンプル2:

chr position value
1   3775200 1
1   3775201 1
1   3775202 10
1   3775203 1
1   3775204 12
1   3775205 1
1   3775206 13
1   3775207 1
1   3775208 1
1   3775209 18

(など...)

目的の出力ファイル:/出力ファイルに任意の値を入れました。

chr, position, value-samp1, value-samp2, value-samp3, value-samp4 
1 50204 2 17 5 2
1 50205 2 17 5 2
1 50206 2 18 5 2
1 50207 2 19 5 3
1 50208 3 19 5 3
1 50209 3 19 5 3

Join、merge、catを試しましたが、期待どおりに動作しませんでした。私は初心者です。これをどのように実行できるのかというアイデアはありますか?

(編集者注:あなたが提供した実際のデータを使用して説明した作業の例です。)

chr position    samp1   samp2
1   3774318     1       0
1   3774319     1       0
1   3775200     2       1
1   3775201     0       1
1   3775202     70      10
1   3775203     7       1
1   3775204     270     12
1   3775205     3       1
1   3775206     5       13
1   3775207     7       1
1   3775208     0       1
1   3775209     0       18

答え1

別のawk方法。NA入力ファイルの1つに特定のバリエーションが存在しない場合は、このファイルが印刷されます。

awk '{ if(FNR==1){files[fnum++]=FILENAME}else{var[$1"\t"$2][FILENAME]=$3}} END{ for(v in var){for(file in files){if(! var[v][files[file]]){var[v][files[file]]="NA"}}}printf "chr\tposition "; for(i=1;i<=fnum;i++){printf "value-samp%s\t",i;} print "";for(v in var){ printf "%s ",v; for(file in var[v]){if(file in var[v]); else{var[v][file]="NA";}  printf "%s\t", var[v][file] } print ""}}' s1 s2

または簡潔さがあまり好きではない場合:

awk '{ 
        if(FNR==1){
            files[fnum++]=FILENAME
        }
        else{
            var[$1"\t"$2][FILENAME]=$3
        }
      } 
      END{ 
        for(v in var){
            for(file in files){
                if(! var[v][files[file]]){
                    var[v][files[file]]="NA"
                }
            }
        }
        printf "chr\tposition "; 
        for(i=1;i<=fnum;i++){
            printf "value-samp%s\t",i;
        } 
        print "";
        for(v in var){ 
            printf "%s ",v; 
            for(file in var[v]){
                if(file in var[v]); 
                else{
                    var[v][file]="NA";
                }
            printf "%s\t", var[v][file];
        } 
    print "";
    }
}' s1 s2

s1とをs2使用している実際のファイル名に変更します。サンプル入力で上記のコマンドを実行すると、以下が返されます。

chr position value-samp1    value-samp2 
1   3774318 1   NA  
1   3775200 2   1   
1   3774319 1   NA  
1   3775201 7   1   
1   3775202 70  10  
1   3775203 7   1   
1   3775204 270 12  
1   3775205 3   1   
1   3775206 5   13  
1   3775207 NA  1   
1   3775208 NA  1   
1   3775209 NA  18  

答え2

取るこのソリューションベースなどの問題の場合、所望の結果を得るには微調整が必​​要です。これは答えではなく、単なる概要であり、いくつかを使用します。擬似コード(sic?) 何をすべきかを簡単に説明します。

Linuxのレビュー参加するコマンドとその能力成功したソリューションにとって非常に重要です。各入力ファイルは、結合する前に特定のフィールド(ここでは染色体番号が使用されているフィールド2)に基づいてソートする必要があります。

結合は2つのファイルしか結合できないため、結合を数回進める必要があるため、いくつかのプログラミング構造と制御メカニズムが必要です。また、指定した空白(空の)値を0に置き換える必要があるため、データ自体を変更する必要があります。

1) 最初のデータファイルを別の名前にコピーします。サンプル_0

2)各ラインを確認してくださいサンプル_0 フィールド 3 の値です。 nullの場合は0に置き換えます。

3) 初期化値Xデータファイルの番号と一致するようにします。

4)各データファイルを連続して使用するには、for / nextループを作成します。どのくらいのデータファイルがありますか?まあ、実行するたびにスクリプトを編集する必要なしにこれを行うには、for / nextループを使用してデータファイルが不足するまでスクリプトを実行します。

5)for / nextループでは2つのことを行います。

5A)次のファイルの各行でフィールド3の値を確認します。 nullの場合は0に置き換えます。

5B) 実行参加するペアリングできない回線を含めます(-ㅏオプション)ファイルの染色体番号(フィールド2)にサンプル_0とファイルサンプル_x 自動書式設定機能があります(オプションを使用)。-o 自動)したがって、両方のファイルにデータがある染色体だけでなく、すべての染色体のデータ行をマージします。サンプル_0とファイルサンプル_x。ファイルへの出力の書き込みサンプル_0

6)他のデータファイルがある場合は追加Xその後、3)を再度実行してください。すべてのデータファイルが接続されたら完了したので、for / nextループを終了します。

答え3

chr常に1であれば無視しても安全なので、今は無視しています。それ以外の場合は、OPでそれがどのように合っているかを説明する必要があります。

awk 'BEGIN {printf "position " }
        FNR>1{ 
        if (FNR==2) {nof+=1; printf ("%s%s " ,"Sam", nof )};
        pos[$2]=$2; data[$2, nof]=$3}
    END { printf "\n"; for (p in pos) {printf ("%s ", pos[p]); 
        for (d=1;d<=nof;d++) printf ("%s ", data[p,d]+0); print "\n"}
    }' file1 file2 | column -t

出力

position  Sam1  Sam2
3774318   1     0
3774319   1     0
3775200   2     1
3775201   7     1
3775202   70    10
3775203   7     1
3775204   270   12
3775205   3     1
3775206   5     13
3775207   0     1
3775208   0     1
3775209   0     18

最初の列見出しを印刷して始めます。

awk 'BEGIN {printf "position " }

すべての最初の行をヘッダーとして無視します。

FNR>1{ 

各ファイルの2行目のファイル数を増やし、ヘッダーを印刷します。

if (FNR==2) {nof+=1; printf ("%s%s " ,"Sam", nof )};

ヘッダーの後ろの各行の位置を配列に配置します。ファイル(サンプル)番号でインデックス付けされた値を含むpos別の配列を設定します。datasampos

pos[$2]=$2; data[$2, nof]=$3}

すべてのファイルを読み取ったら、newlineヘッダーにaを印刷してから、pos各場所を繰り返し印刷します。

END { printf "\n"; for (p in pos ) {printf ("%s ", pos[p]); 

次に、/ file番号dataでインデックス付けされた配列を繰り返して、データがなくても何かが印刷されるようにnull値に0を追加してからaを印刷します。psamdatanewline

for (d=1;d<=nof;d++) printf ("%s ", data[p,d]+0); print "\n"}

ファイルを入力して出力をパイプしてcolumn見やすくします。

}' file1 file2 | column -t

追加されたキャラクター別のインデックスだと仮定

awk 'BEGIN {printf "chr position " }
        FNR>1{
        if (FNR==2) {nof+=1; printf ("%s%s " ,"Sam", nof )};
        chr[$1]=$1; pos[$2]=$2; data[$1, $2, nof]=$3}
    END { printf "\n"; for (c in chr) {for (p in pos ) {printf ("%s %s ", chr[c], pos[p]); 
        for (d=1;d<=nof;d++) printf ("%s ", data[c, p, d]+0); print "\n"}
    }}' file1 file2 | column -t

答え4

ミラーの使用(https://github.com/johnkerl/miller)あなたは実行することができます

mlr --c2p --ifs ' '  --repifs \
sort -f chr,position,value \
then nest --implode --values --across-records -f value \
then nest --explode --across-fields --values -f value \
then unsparsify then clean-whitespace input0*.csv >output.csv

そして得る

chr position value_1 value_2
1   3774318  1       -
1   3774319  1       -
1   3775200  1       2
1   3775201  1       7
1   3775202  10      70
1   3775203  1       7
1   3775204  12      270
1   3775205  1       3
1   3775206  13      5
1   3775207  1       -
1   3775208  1       -
1   3775209  18      -

メモ:

  • コマンドを入力ファイルの名前に合わせて調整する必要があります。私の例ではinput0*.csv
  • 真のCSV出力が必要な場合--c2pに変更してください--csv

関連情報