異なる列の連続セルが同じ場合は、シェルスクリプトを使用して列の単語数を計算する方法!

異なる列の連続セルが同じ場合は、シェルスクリプトを使用して列の単語数を計算する方法!

2列、3列、1列の連続セルが等しい場合、9列のC_R合計数を計算しようとします。S_Rファイルはベッド形式(タブ区切り形式)です。元のファイルは大きく、最初の列は染色体番号を定義します。ファイルの最初の数行は次のとおりです。

chr1    10200   10300   8   10000   10214   100 214 S_R
chr1    10200   10300   8   10009   10233   100 224 S_R
chr1    10200   10300   8   10014   10220   100 206 S_R
chr1    10200   10300   8   10045   10215   100 170 S_R
chr1    10200   10300   8   10068   10209   100 141 S_R
chr1    10200   10300   8   10074   10300   100 226 C_R
chr1    10200   10300   8   10182   10283   100 101 S_R
chr1    10200   10300   8   10182   10387   100 205 C_R
chr1    10300   10400   4   10182   10387   100 205 S_R
chr1    10300   10400   4   10331   10467   100 136 S_R
chr1    10300   10400   4   10346   10461   100 115 S_R
chr1    10300   10400   4   10352   10468   100 116 S_R
chr1    10400   10500   3   10331   10467   100 136 S_R
chr1    10400   10500   3   10346   10461   100 115 S_R
chr1    10400   10500   3   10352   10468   100 116 S_R
chr1    11000   11100   2   11024   11163   100 139 S_R
chr1    11000   11100   2   11024   11188   100 164 S_R
chr1    11100   11200   3   11024   11163   100 139 S_R
chr1    11100   11200   3   11024   11188   100 164 S_R
chr1    11100   11200   3   11127   11296   100 169 S_R
chr1    11200   11300   1   11127   11296   100 169 S_R
chr1    11400   11500   2   11412   11561   100 149 S_R
chr1    11400   11500   2   11457   11608   100 151 S_R
chr1    11500   11600   3   11412   11561   100 149 S_R
chr1    11500   11600   3   11457   11608   100 151 C_R
chr1    11500   11600   3   11574   11744   100 170 S_R
chr1    11600   11700   3   11457   11608   100 151 S_R
chr1    11600   11700   3   11574   11744   100 170 C_R
chr1    11600   11700   3   11640   11815   100 175 S_R
chr1    11700   11800   4   11574   11744   100 170 S_R
chr1    11700   11800   4   11640   11815   100 175 C_R
chr1    11700   11800   4   11784   11963   100 179 S_R
chr1    11700   11800   4   11791   11936   100 145 S_R

上記の表の最初の8行で、列1、2、3が同じであるため、一時出力ファイルは次のようになります。

chr1    10200   10300   2   6
chr1    10300   10400   0   4
chr1    10400   10500   0   3
chr1    11000   11100   0   2
chr1    11100   11200   0   3
chr1    11200   11300   0   1
chr1    11400   11500   0   2
chr1    11500   11600   1   2
chr1    11600   11700   1   2
chr1    11700   11800   1   3

出力ファイルでは、列4C_Rと5は次のようになります。S_R

答え1

awkこれは次の方法で行うことができます。

awk 'function report() {
       if (n) print last_key, 0+count["C_R"], 0+count["S_R"]
     }
     {key = $1 OFS $2 OFS $3}
     key != last_key {report(); n = 0; split("", count); last_key = key}
     {count[$9]++; n++}
     END {report()}' <your-file

-F '\t' -v OFS='\t'入力フィールドがタブで区切られている場合は、入力ファイルと出力ファイルの区切り文字を追加して指定する必要があります。デフォルトFSでは、入力フィールド区切り文字(によって設定されます-F)は特別な意味を持つ空白文字です。フィールドを区切る空白のシーケンスと、先頭と末尾の空白が削除されるか、IOW フィールドが空白ではない文字のシーケンスです。したがって、空のフィールドは存在できず、OFS空白でもあります。これは、単に出力のフィールドがスペースで区切られていることを意味します。

答え2

これはGNU(awkほとんどのLinuxシステムのgawkデフォルト)メソッドです。awkここでは、列がタブで区切られていると仮定していますが、これはbedファイルまたはbedpeファイルのように見えるため、どちらもタブが必要なので、これが正しいと合理的に確信しています。

$ gawk -F'\t' -v OFS='\t' -v type1="C_R" -v type2="S_R" '
  { 
    a[$1 OFS $2 OFS $3][$NF]++; 
  } 
  END{ 
    for (i in a){  
      print i,0+a[i][type1],0+a[i][type2]
    }
}' file.bed 
chr1    11200   11300   0   1
chr1    11700   11800   1   3
chr1    10300   10400   0   4
chr1    11000   11100   0   2
chr1    10400   10500   0   3
chr1    11500   11600   1   2
chr1    11400   11500   0   2
chr1    11100   11200   0   3
chr1    11600   11700   1   2
chr1    10200   10300   2   6

説明する

-F'\t'入力フィールド区切り記号をタブに設定し、-v OFS='\t'出力フィールド区切り記号をタブに設定します。次に、スクリプトで使用するtype12つの異なる変数を設定します。type2

スクリプトの本文は右a[$1 OFS $2 OFS $3][$NF]++;。これは、出力フィールド区切り文字(この場合はタブ)で区切られた最初の3つのフィールドをOFS2D配列の最初のキーとして使用しますa。 2番目のキーは最後のフィールド($NF)で、値に1を追加するだけです。したがって、a配列は、各可能な最後のフィールドで、各文字、開始位置、および終了位置が見つかった回数を計算します。

完了したら、END{ }ブロック内の配列のすべてのキー(文字、開始位置、終了位置)を繰り返し、次に文字、開始位置、終了位置(値)を持つ2つのa最後のフィールドをそれぞれ印刷します。 of)、次に、最後の可能な各フィールドが最初の3つのフィールド()で表示される回数です。これらの文字、開始位置、終了位置に特定の最後のフィールドが表示されない場合は、空のフィールドの代わりにエラーが発生する必要があります。type1type2i0+a[i][type1],0+a[i][type2]0+0

答え3

TSV認識ユーティリティMiller(mlr)を使用して入力をヘッダーなしのTSVファイルに読み込み、必要な列のみを選択して(使用cut)、列9の値を;各列の組み合わせ1の区切りリストに収集/縮小します。 2と3(使用)を使用して、残りの各レコードについて収集された合計文字列の数を計算しますnest(式を使用)。 9列の縮小値は最終的に削除されます(with)。C_RS_Rputcut -x

mlr --from=file --tsv -N \
    cut -f 1,2,3,9 then \
    nest --ivar ';' -f 9 then \
    put '
        a = splita($9,";");
        for (k in ["C_R","S_R"]) {
            $[k] = count(select(a, func(e) { return e == k }))
        }' then \
    cut -x -f 9

質問のデータが与えられると、次のタブで区切られた出力が生成されます。

chr1    10200   10300   2       6
chr1    10300   10400   0       4
chr1    10400   10500   0       3
chr1    11000   11100   0       2
chr1    11100   11200   0       3
chr1    11200   11300   0       1
chr1    11400   11500   0       2
chr1    11500   11600   1       2
chr1    11600   11700   1       2
chr1    11700   11800   1       3

答え4

使用幸せ(以前のPerl_6)

~$ raku -e 'my @a = lines.map: *.split(/\s+/);  \
            my %hash.push:  [Z=>] @a.map(*.[0..2]), @a.map(*.[*-1]);  \
            put join "\t", .key, (.value.map: * eq "C_R")>>.Int.sum,  \
                (.value.map: * eq "S_R")>>.Int.sum  for %hash.sort;'  file

これはPerlプログラミング言語の1つであるRakuで書かれた答えです。lines空白には上記の内容がmap挿入されています。split結果は@a配列に保存されます。%hashAを宣言し、[Z=>] Rakuの縮小メタ演算子を使用して、最初の3つの列と一緒にpushキー/値のペアをここに追加します。.[0..2]最後の.[*-1]列は。最後のステートメントでは、文字列valueseqC_Rsが有効であることを確認してください。各ブール結果は、med列とout列にS_R変換されます。Intsumput

入力例:

chr1    10200   10300   8   10000   10214   100 214 S_R
chr1    10200   10300   8   10009   10233   100 224 S_R
chr1    10200   10300   8   10014   10220   100 206 S_R
chr1    10200   10300   8   10045   10215   100 170 S_R
chr1    10200   10300   8   10068   10209   100 141 S_R
chr1    10200   10300   8   10074   10300   100 226 C_R
chr1    10200   10300   8   10182   10283   100 101 S_R
chr1    10200   10300   8   10182   10387   100 205 C_R
chr1    10300   10400   4   10182   10387   100 205 S_R
chr1    10300   10400   4   10331   10467   100 136 S_R
chr1    10300   10400   4   10346   10461   100 115 S_R
chr1    10300   10400   4   10352   10468   100 116 S_R
chr1    10400   10500   3   10331   10467   100 136 S_R
chr1    10400   10500   3   10346   10461   100 115 S_R
chr1    10400   10500   3   10352   10468   100 116 S_R
chr1    11000   11100   2   11024   11163   100 139 S_R
chr1    11000   11100   2   11024   11188   100 164 S_R
chr1    11100   11200   3   11024   11163   100 139 S_R
chr1    11100   11200   3   11024   11188   100 164 S_R
chr1    11100   11200   3   11127   11296   100 169 S_R
chr1    11200   11300   1   11127   11296   100 169 S_R
chr1    11400   11500   2   11412   11561   100 149 S_R
chr1    11400   11500   2   11457   11608   100 151 S_R
chr1    11500   11600   3   11412   11561   100 149 S_R
chr1    11500   11600   3   11457   11608   100 151 C_R
chr1    11500   11600   3   11574   11744   100 170 S_R
chr1    11600   11700   3   11457   11608   100 151 S_R
chr1    11600   11700   3   11574   11744   100 170 C_R
chr1    11600   11700   3   11640   11815   100 175 S_R
chr1    11700   11800   4   11574   11744   100 170 S_R
chr1    11700   11800   4   11640   11815   100 175 C_R
chr1    11700   11800   4   11784   11963   100 179 S_R
chr1    11700   11800   4   11791   11936   100 145 S_R

出力例:

chr1 10200 10300    2   6
chr1 10300 10400    0   4
chr1 10400 10500    0   3
chr1 11000 11100    0   2
chr1 11100 11200    0   3
chr1 11200 11300    0   1
chr1 11400 11500    0   2
chr1 11500 11600    1   2
chr1 11600 11700    1   2
chr1 11700 11800    1   3

putすべての列をタブで区切るには、[最後のドアから.key]に置き換えます。.key.split(" ").join("\t")


中間のステップを見ると非常に理解しやすいことが多いので、次はマイニングの.raku最後の2列sum前にデータ()のRakuの内部表現です。

~$ raku -e 'my @a = lines.map: *.split(/\s+/); my %hash.push:  [Z=>] @a.map(*.[0..2]), @a.map(*.[*-1]); .raku.say for %hash.sort;'  file
"chr1 10200 10300" => $["S_R", "S_R", "S_R", "S_R", "S_R", "C_R", "S_R", "C_R"]
"chr1 10300 10400" => $["S_R", "S_R", "S_R", "S_R"]
"chr1 10400 10500" => $["S_R", "S_R", "S_R"]
"chr1 11000 11100" => $["S_R", "S_R"]
"chr1 11100 11200" => $["S_R", "S_R", "S_R"]
"chr1 11200 11300" => "S_R"
"chr1 11400 11500" => $["S_R", "S_R"]
"chr1 11500 11600" => $["S_R", "C_R", "S_R"]
"chr1 11600 11700" => $["S_R", "C_R", "S_R"]
"chr1 11700 11800" => $["S_R", "C_R", "S_R", "S_R"]

https://docs.raku.org/言語/hashmap
https://raku.org

関連情報