Как случайным образом изменить порядок двух столбцов одновременно 1000 раз, используя значения моделирования?

Как случайным образом изменить порядок двух столбцов одновременно 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    

Мне нужно создать 2 столбца с именами «simulation1» и «simulation2» со случайными числами внутри них, как показано ниже:

 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

После этого я сортирую столбцы «ID» и «pheno» по значению в столбце «simulation1», затем вычисляю среднее значение «pheno» для верхних 40% строк, которое будет равно 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 

Затем я сортирую столбцы «ID» и «pheno» по значению в столбце «simulation2», затем вычисляю среднее значение «pheno» для верхних 40% строк, которое будет равно 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.

Для второго раунда первые два столбца (ID и pheno) останутся неизменными, но мне нужно создать новые значения в столбцах "simulation1" и "simulation2". Я создаю значения в "simulation1" и "simulation2" в Excel с помощью функции 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) Мне нужно создать 2 столбца с именами «simulation1» и «simulation2» со случайными числами внутри них.

$ 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) после этого я сортирую столбцы "ID" и "pheno" по значению в столбце "simulation1"

$ 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) затем я вычисляю среднее значение "pheno" для верхних 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он не очень хорошо сочетался с ведущими знаками в числах, поэтому был изменен awkна domath.

Также изменено использование 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

Связанный контент