Wie kann man die Reihenfolge zweier Spalten mithilfe von Simulationswerten 1000 Mal gleichzeitig zufällig ändern?

Wie kann man die Reihenfolge zweier Spalten mithilfe von Simulationswerten 1000 Mal gleichzeitig zufällig ändern?

Meine Daten sehen so aus:

    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    

Ich sollte zwei Spalten mit den Namen „Simulation1“ und „Simulation2“ erstellen, die Zufallszahlen enthalten, wie unten:

 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

danach sortiere ich die Spalten „ID“ und „pheno“ nach dem Wert in der Spalte „simulation1“, dann berechne ich den Durchschnitt von „pheno“ für die oberen 40 % der Zeilen, der 0,193 = (0,12+0,32+0,0003+0,33)/4 beträgt

 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 

Dann sortiere ich die Spalten „ID“ und „pheno“ nach dem Wert in der Spalte „simulation2“ und berechne dann den Durchschnitt von „pheno“ für die oberen 40 % der Zeilen, der 0,1 = (-0,81+0,33+0,553+0,33)/4 beträgt.

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

Dann würde die Differenz zwischen den Durchschnittswerten der oberen 40 % bei unterschiedlichen Sortierungen -0,093 = 0,1 – 0,193 betragen.

Für die zweite Runde bleiben die ersten beiden Spalten (ID und Pheno) unverändert, aber ich sollte neue Werte in den Spalten „Simulation1“ und „Simulation2“ erstellen. Ich erstelle Werte in „Simulation1“ und „Simulation2“ in Excel mithilfe der Funktion RAND()*. Aber es ist mir unmöglich, dies 1000 Mal zu wiederholen. Ich frage mich, wie ich in Linux eine Schleife für das erstellen kann, was ich möchte.

Die endgültige Ausgabe lautet:

row_name top40%average_simulate1  top40%average_simulate2  difference 

   1          0.193                    0.1                    -0.093
   2          
   .
   .
   .
   1000   

Antwort1

In allen Fällen | column -twird das Folgende nur hinzugefügt, um die Ausgabe optisch anzugleichen.

1) Ich sollte zwei Spalten mit den Namen "Simulation1" und "Simulation2" erstellen, die Zufallszahlen enthalten.

$ 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) danach sortiere ich die Spalten "ID" und "pheno" nach dem Wert in der Spalte "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) dann berechne ich den Durchschnitt von „Phäno“ für die oberen 40 % Zeilen

$ 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

Ich nehme an, Sie können den Rest selbst herausfinden. Oben habe ich awk bei jedem Aufruf den gleichen Seed zugewiesen, damit die Ausgabe konstant bleibt und die Berechnungsphasen leichter nachverfolgt werden können. Ändern Sie die Aufrufe, um tst.awkbei awk -v seed="$RANDOM" -f tst.awkjedem Aufruf unterschiedliche Zufallszahlen zu generieren.

Antwort2

Ein aktualisiertes Skript, da bces mit den Vorzeichen der Zahlen nicht gut funktionierte und daher awkin geändert wurde domath.

Außerdem wurde die Änderung auf die Verwendung shufzum Mischen der Array-Indizes für jede Iteration geändert, da dies mit einem festen Array einfacher ist.

#!/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

verwandte Informationen