我正在尝试计算以下文件中所有可用列的标准偏差。
输入文件:
2017 04 15 00 00 00 36.606 -97.488 316.200 233.230 0.10 950.840 0.40
2017 04 15 00 00 01 36.606 -97.488 316.200 245.220 0.10 911.540 0.40
2017 04 15 00 00 02 36.606 -97.488 316.200 246.460 0.10 958.790 0.40
2017 04 15 00 00 03 36.606 -97.488 316.200 216.880 0.10 902.750 0.40
2017 04 15 00 00 04 36.606 -97.488 316.200 213.280 0.10 854.170 0.40
2017 04 15 00 00 05 36.606 -97.488 316.200 200.360 0.10 879.040 0.40
2017 04 15 00 00 06 36.606 -97.488 316.200 204.250 0.10 951.800 0.40
2017 04 15 00 00 07 36.606 -97.488 316.200 224.270 0.10 1015.570 0.40
2017 04 15 00 00 08 36.606 -97.488 316.200 203.490 0.10 849.640 0.40
2017 04 15 00 00 09 36.606 -97.488 316.200 198.620 0.10 969.190 0.40
2017 04 15 00 00 10 36.606 -97.488 316.200 213.530 0.10 896.930 0.40
2017 04 15 00 00 10 36.606 -97.488 316.200 216.300 0.10 1005.490 0.40
我正在使用以下行计算所有列的标准偏差:
awk '{for(i=1;i<=NF;i++){a[i]+=$i; s[i]+=$i*$i}}END{for(i=1;i<=NF;i++) {print sqrt(s[i]/NR-(a[i]/NR)^2)}}' infile > outfile
这将根据我的要求计算所有列的标准偏差。但是,当我使用gnu awk(gawk)而不是awk时,它的计算结果相同,但带有以下警告:
awk: cmd. line:1: (FILENAME=infile FNR=3600) warning: sqrt: called with a negative argument -5.63438e-15
我无法理解awk和gawk之间的区别是什么给我这个警告。
谢谢
根据定义,输入数据的方差(标准偏差的平方)通过以下公式计算:
这里的问题是无法确定平均值(x-bar)值直到所有数据被阅读。因此,以上方程式不适合用于实际的实现。在实践中,等式转换为:
适用于逐数据计算。
尽管这些方程式是理论上等价的,第二个方程式由于舍入误差可能会产生负值。如果所有数据都相同(与值本身无关)。
可能的解决方法是将负值的方差设置为零正如我在评论中指出的那样。另一个解决方法是使用以下方法返回原始定义:
awk 'NR==FNR {
for (i=1; i<=NF; i++)
sum[i]+=$i
next
}
# following lines are executed in the 2nd iteration
FNR==1 {
n=NR-1
for (i=1; i<=NF; i++)
mean[i]=sum[i]/n
}
{
for (i=1; i<=NF; i++)
sum2[i]+=($i-mean[i])*($i-mean[i])
}
END {
for(i=1; i<=NF; i++)
print sqrt(sum2[i]/n)
}' infile infile > outfile
效率较低,因为它两次读取数据。