我有一個數據看起來像這樣:
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
之後,我根據「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。
對於第二輪,前兩列(ID 和 pheno)將保持不變,但我應該在「simulation1」和「simulation2」欄中建立新值。我使用函數 RAND()* 在 Excel 中的“simulation1”和“simulation2”中建立值。但我不可能重複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”,其中包含隨機數
$ 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% 行的「pheno」平均值
$ 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 提供了相同的種子,以便輸出保持不變,以便於追蹤整個計算階段。變更對 to 的調用,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