2013-09-13 2 views
13

У меня есть файл file.dat с 24 (строками) x 16 (столбцами) данных.Среднее вычисление и стандартное отклонение с awk

Я уже протестировал следующий скрипт awk, который вычисляет среднее значение для каждого столбца.

touch aver-std.dat 
awk '{ for (i=1; i<=NF; i++) { sum[i]+= $i } } 
END { for (i=1; i<=NF; i++) 
{ printf "%f \n", sum[i]/NR} }' file.dat >> aver-std.dat 

Выход «aver-std.dat» имеет один столбец с этими средними значениями.

Аналогично среднему вычислению Я хотел бы вычислить стандартное отклонение каждого столбца файла данных file.dat и записать его во второй столбец выходного файла. А именно, мне нужен выходной файл со средним значением в первом столбце и стандартным отклонением во втором столбце.

Я делал различные тесты, как этот

touch aver-std.dat 
awk '{ for (i=1; i<=NF; i++) { sum[i]+= $i }} 
END { for (i=1; i<=NF; i++) 
{std[i] += ($i - sum[i])^2 ; printf "%f %f \n", sum[i]/NR, sqrt(std[i]/(NR-1))}}' file.dat >> aver-std.dat 

и записывает значения во втором столбце, но они не правильное значение стандартного отклонения. Вычисление отклонения некорректно. Буду признателен за любую помощь. С уважением

ответ

-1

Ваш скрипт должен быть как-то в этой форме вместо:

awk '{ 
    sum = 0 
    for (i=1; i<=NF; i++) { 
     sum += $i 
    } 
    avg = sum/NF 
    avga[NR] = avg 
    sum = 0 
    for (i=1; i<=NF; i++) { 
     sum += ($i - avg)^2 
    } 
    stda[NR] = sqrt(sum/NF) 
} 

END { for (i = 1; i in stda; ++i) { printf "%f %f \n", avga[i], stda[i] } }' file.dat >> aver-std.dat 
+0

Это неверно для заданного вопроса, так как он вычисляет std dev для каждой ** строки **, а не для каждого столбца, как запрошено OP. – shiri

23

Стандартное отклонение

stdev = sqrt((1/N)*(sum of (value - mean)^2)) 

Но есть другой вид формулы, которая не требует, чтобы вы знали среднее заранее. Это:

stdev = sqrt((1/N)*((sum of squares) - (((sum)^2)/N))) 

(быстрый поиск веб-за «суммы квадратов» формулу стандартного отклонения даст вам вывод, если вы заинтересованы)

Чтобы использовать эту формулу, вы должны следить за как сумму, так и сумму квадратов значений. Так что ваш AWK сценарий изменится:

awk '{for(i=1;i<=NF;i++) {sum[i] += $i; sumsq[i] += ($i)^2}} 
      END {for (i=1;i<=NF;i++) { 
      printf "%f %f \n", sum[i]/NR, sqrt((sumsq[i]-sum[i]^2/NR)/NR)} 
     }' file.dat >> aver-std.dat 
+1

Привет! Большое спасибо. Это решение работает нормально. – PLM

+1

Я только должен был добавить, что это было квазистандартное отклонение и должно делить на (NR-1). С уважением и благодарностью. – PLM

+0

@PLM, объясните свой последний комментарий? В блоке 'END',' NR' имеет общее количество строк, что делает это правильным решением. – shiri

4

Вот некоторые вычисления я сделал на выходе мясорубки файла данных для теста замочить, который должен был быть прерван:

Стандартное отклонение (предвзятым) + средний:

cat <grinder_data_file> | grep -v "1$" | awk -F ', ' '{ sum=sum+$5 ; sumX2+=(($5)^2)} END { printf "Average: %f. Standard Deviation: %f \n", sum/NR, sqrt(sumX2/(NR) - ((sum/NR)^2))}' 

Стандартное отклонение (не предвзято) + средний:

cat <grinder_data_file> | grep -v "1$" | awk -F ', ' '{ sum=sum+$5 ; sumX2+=(($5)^2)} END { avg=sum/NR; printf "Average: %f. Standard Deviation: %f \n", avg, sqrt(sumX2/(NR-1) - 2*avg*(sum/(NR-1)) + ((NR*(avg^2))/(NR-1)))}' 
+0

Существует также другой способ расчета стандартного отклонения с учетом того, что арифметика с плавающей точкой может привести к отмене. Проверка на B. P. Welford (1962). [«Замечание о методе вычисления скорректированных сумм квадратов и произведений»] (http://www.jstor.org/stable/1266577?seq=1#page_scan_tab_contents). Technometrics 4 (3): 419-420 –

5

Чтобы просто рассчитать стандартное отклонение списка чисел, вы можете использовать команду:

awk '{x+=$0;y+=$0^2}END{print sqrt(y/NR-(x/NR)^2)}' 

^ в POSIX. ** поддерживается gawk и nawk, но не на mawk.

+0

Спасибо @nisetama; Я использовал это. Для полноты среднее значение можно вычислить аналогично с однострочным 'awk '{x + = $ 0} END {print x/NR}'' –

Смежные вопросы