シミュレートされた値を使用して、2つの列の順序を同時に1000回ランダムに変更するには?

シミュレートされた値を使用して、2つの列の順序を同時に1000回ランダムに変更するには?

次のデータがあります。

    ID    pheno  

    231   0.12     
    432   0.32     
    11    0.0003   
    134   0.33     
    2334  0.553    
    12    0.33     
    100   0.331    
    1008  1.6      
    223  -0.81     
    998  -3.001    

次のように、乱数を含む「simulation1」と「simulation2」という2つの列を作成する必要があります。

 ID    pheno  simulation1 simulation2

134   0.33     4.11   0.004
2334  0.553    83     0.44
12    0.33     87     0.55
100   0.331    88     12 
231   0.12     0.1    2 
432   0.32     3      30
11    0.0003   3.5    11
1008  1.6      89     23
223  -0.81     113    0.001
998  -3.001    220    982

次に、「simulation1」列の値に基づいて「ID」列と「pheno」列をソートし、行の最初の40%の「pheno」平均を計算します。つまり、0.193 = (0.12+ 0.32+0.0003+0.33) /4

 ID    pheno  simulation1 simulation2

231   0.12     0.1    2 
432   0.32     3      30
11    0.0003   3.5    11
134   0.33     4.11   0.004
2334  0.553    83     0.44
12    0.33     87     0.55
100   0.331    88     12
1008  1.6      89     23
223  -0.81     113    0.001
998  -3.001    220    982 

次に、「simulation2」列の値に基づいて「ID」列と「pheno」列をソートし、行の最初の40%の「pheno」平均を計算しました。つまり、0.1=(-0.81+0.33)+0.553+0.33)/4

ID    pheno  simulation1 simulation2

223  -0.81     113    0.001
134   0.33     4.11   0.004
2334  0.553    83     0.44
12    0.33     87     0.55
231   0.12     0.1    2
11    0.0003   3.5    11
100   0.331    88     12
1008  1.6      89     23
432   0.32     3      30
998  -3.001    220    980

これにより、異なるランキングを使用した上位40%の平均の差は、-0.093 = 0.1 - 0.193になります。

2回目のラウンドでは、最初の2つの列(IDとpheno)は同じままですが、「simulation1」列と「simulation2」列に新しい値を作成する必要があります。 Excelで「simulation1」と「simulation2」に値を生成するには、RAND()*関数を使用します。しかし、1000回も繰り返すことはできません。 Linuxで目的のループを作成する方法を知りたいです。

最終出力は次のとおりです。

row_name top40%average_simulate1  top40%average_simulate2  difference 

   1          0.193                    0.1                    -0.093
   2          
   .
   .
   .
   1000   

答え1

すべての場合に、| column -t以下を追加して出力を視覚的にソートします。

1)乱数を含む「simulation1」と「simulation2」の2つの列を作成する必要があります。

$ cat tst.awk
BEGIN { srand(seed) }
{ print $0, r(), r() }
function r() { return rand() * 100001 / 1000 }

$ awk -f tst.awk file | column -t
231   0.12    85.5574  23.7444
432   0.32    23.558   65.5853
11    0.0003  59.2486  50.3799
134   0.33    27.8248  45.7872
2334  0.553   45.7947  13.1887
12    0.33    51.6042  99.55
100   0.331   88.0281  17.4515
1008  1.6     1.37974  65.5945
223   -0.81   14.6773  97.6476
998   -3.001  87.888   31.97

2)その後、「simulation1」列の値に基づいて「ID」列と「pheno」列を並べ替えます。

$ awk -f tst.awk file | sort -k3,3n | column -t
1008  1.6     1.37974  65.5945
223   -0.81   14.6773  97.6476
432   0.32    23.558   65.5853
134   0.33    27.8248  45.7872
2334  0.553   45.7947  13.1887
12    0.33    51.6042  99.55
11    0.0003  59.2486  50.3799
231   0.12    85.5574  23.7444
998   -3.001  87.888   31.97
100   0.331   88.0281  17.4515

3)次に、行の最初の40%の平均「フェノ」を計算します。

$ cat tst2.awk
{ vals[NR] = $2 }
END {
    max = NR * 40 / 100
    for (i=1; i<=max; i++) {
        sum += vals[i]
    }
    print sum / max
}

$ awk -f tst.awk file | sort -k3,3n | awk -f tst2.awk
0.36

残りはあなたが理解できることを願っています。上記では、出力が同じになるように、すべての呼び出しに同じシードをawkに渡すことで、計算ステップ全体を簡単に追跡できます。呼び出しごとに異なる乱数が生成さtst.awkれるように、呼び出しをに変更します。awk -v seed="$RANDOM" -f tst.awk

答え2

更新されたスクリプトは数字bcの先頭記号とうまく機能しません。awkdomath

また、shuf固定配列を使用する方が簡単なので、繰り返しごとに混合するために配列インデックスを使用するように変更されました。

#!/bin/bash

function domath {
    #do the math using the 4 indices into the pheno array
    awk '{print ($1+$2+$3+$4)/4}' <<<"${ph[$1]} ${ph[$2]} ${ph[$3]} ${ph[$4]}"
}

function iterate {
    #randomise the indices and get the first 4
    shuf -e 0 1 2 3 4 5 6 7 8 9 | head -n 4
}

#number of iterations
nits=100

#read the pheno values into an array
ph=($(tail -n +3 data | awk '{print $2}'))


echo -e row'\t'sim1'\t'sim2'\t'diff
for (( row=1; row<=$nits; row++ )); do
    #calculate simulation1 
    first=$(printf "%+.3f" $(domath $(iterate)))
    #calculate simulation 2
    second=$(printf "%+.3f" $(domath $(iterate)))
    #calculate the difference
    diff=$(printf "%+.3f" $(awk '{print $2-$1}' <<<"$first $second"))
    #and print
    echo -e $row'\t'$first'\t'$second'\t'$diff
done

関連情報