warning sqrt:在gnu awk中用负参数调用

问题描述 投票:0回答:1

我正在尝试计算以下文件中所有可用列的标准偏差。

输入文件:

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之间的区别是什么给我这个警告。

谢谢

linux bash shell ubuntu awk
1个回答
0
投票

根据定义,输入数据的方差(标准偏差的平方)通过以下公式计算:

enter image description here

这里的问题是无法确定平均值(x-bar)值直到所有数据被阅读。因此,以上方程式不适合用于实际的实现。在实践中,等式转换为:

enter image description here

适用于逐数据计算。

尽管这些方程式是理论上等价的,第二个方程式由于舍入误差可能会产生负值。如果所有数据都相同(与值本身无关)。

可能的解决方法是将负值的方差设置为零正如我在评论中指出的那样。另一个解决方法是使用以下方法返回原始定义:

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

效率较低,因为它两次读取数据。

© www.soinside.com 2019 - 2024. All rights reserved.