2つの列で定義された2つの値の間の値をカウントする

2つの列で定義された2つの値の間の値をカウントする

次のように 3 つの列に保存されたデータがあります。

3651 3631 3913
3667 3996 4276
3674 4486 4605
3707 4706 5095
3720 5174 5326
3750 5439 5899
3755 5928 6263
3767 6437 7069
3779 7157 7232
3882 7384 7450
3886 7564 7649
3900 7762 7835
4006 7942 7987
4015 8236 8325
4026 8417 8464
4065 8571 8737
4156 6790 7069
4493 7157 7450
4541 7564 7649
4551 7762 7835
4597 7942 7987
4756 8236 8325
4776 8417 8464

ここで、1 列目は特定の値、2 列目は開始、3 列目は終了です。1 列目には 825849 行、2 列目と 3 列目には 58386 行あります。開始と終了の間にある場合は、1 列目から値をカウントする必要があります。

私のファイルでは、列番号 1 の最初の 12 個の特定の値が最初の開始と終了の間にあり、次の 5 個が 2 番目の開始と終了の間にある、などであることがわかっています。ファイル全体をチェックする必要があります。これを試してみましたが、うまくいきましたが、非常に遅いです。

coords='final_exons.txt'

snp=( $( cat $coords | awk '{print $1}') )
exon_start=( $( cat $coords | awk '{print $2}') )
exon_end=( $( cat $coords | awk '{print $3}') )

i=0
counter=0
for value in ${exon_end[@]}; do
    new_val=$counter
    counter=0
    let "i++"
    for snps in ${snp[@]}; do

        if [[ $value > $snps ]]; then
            #statements
            let "counter++"
            #$counter=$(echo "scale=2; $counter-$new_val" | bc)
        else
            #$new_val=$(echo "scale=2; $counter-$")
            break
        fi
    done
    #echo "NOWENOWE $new_val "
    #echo "COUNTER $value : $counter "
    final=$(echo "scale=2; sqrt(($counter-$new_val)^2)" | bc)
    echo "Exon $i : $final SNPs"
done

ヒントやアドバイスがあればよろしくお願いします

完全なデータへのリンク

答え1

  1. 各値を1行に入力しますが、「開始」と「終了」を または で追加してマークしますSE次に、値を数値順に並べ替えます。次のようになります。
3631S
3651
3667
...
3900
3913E
3996S
4006
...
  1. Saと終了値の間の出現回数をカウントしますE

脚本を書いて幸せになりましょう!

awk '
    {print $1} 
    $3!="" {print $2"S"; print $3"E"} 
' final_exons.txt | sort -n | awk '
    !/E|S/ {count++; next}
    /S/ {count=0; next}
    /E/ {print line++": "count}'

最初にawk、ステップ 1 を実行します。1 列目には 2 列目や 3 列目よりも多くの行があるため、テストsortが行​​われます$3!=""( の場合もあります)。$2!=""

2 番目はawkステップ 2 に対応します。 を含む行を読み取った場合はカウンターをリセットしS、行にマーカーがない場合はカウンターを増分し、 を含む行を読み取った場合はカウンターを (行番号とともに) 出力しますE

提供されたサンプル ファイルで実行した場合の出力は次のようになります0: 12; 1: 5; 2: 4; 3: 2; ...; 22: 0

答え2

awk を使うこともできます:

awk '{if( ($1 > $2) && ($1 < $3) ){print NR" "$1" "$2" "$3}}' final_exons.txt

しかし、col1 と (col2 と col3) が別々に処理される場合は、それらを別々のファイルに切り離す方がよいでしょう。または、データをデータベースに入れて、その中で間隔テストを実行します。ただし、最も効率的な方法は、データを通常の配列にロードし、テスト ループを他のスクリプト言語 (php、python、perl ...) で実現することです。

関連情報