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 -t
wird 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.awk
bei awk -v seed="$RANDOM" -f tst.awk
jedem Aufruf unterschiedliche Zufallszahlen zu generieren.
Antwort2
Ein aktualisiertes Skript, da bc
es mit den Vorzeichen der Zahlen nicht gut funktionierte und daher awk
in geändert wurde domath
.
Außerdem wurde die Änderung auf die Verwendung shuf
zum 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