模式旁边数字的标准差

模式旁边数字的标准差

我有一个包含很多标签的文件,标签旁边有一个数字,如下所示:

<Score>4
... other data
<Score>2
... other data
<Score>3

等等...

我使用 grep 来获取一行中出现的次数

grep -c '<Score>' $1

我使用 awk 计算了分数的总和:

awk 'sub(/<Score>/,""){y+=$0} END{print y}' $1}

然后将其除以我从 grep 得到的数字以获得平均值。

我正在努力解决的是如何从 <Score> 旁边的每个值中取出平均值,将其平方,然后将它们加在一起。

平均值存储在变量 $mean 中我尝试过的代码如下所示:

awk 'sub(/<Score>/,""){y+=($0-$mean)^2} END{print y}' $1

然而它一直输出 0,如果我可以将其存储在变量中,那么我将能够使用所有其他变量来计算标准差。

答案1

这里有一些实用程序供您使用。第一个计算给它的数字的平均值(每行一个数字)。第二个使用第一个来计算文件中数字的标准偏差。


可执行文件average

#!/usr/bin/awk -f

/^[0-9.+-]/     { sum += $0; ++n }

END             { print sum / n }

awk脚本将从文件或标准输入读取输入并计算其中数字的平均值。它期望每行一个数字。


可执行文件stdev

#!/bin/sh

awk -v avg="$( ./average "$1" )" \
    '/^[0-9.+-]/ { sum += ($0 - avg)^2; ++n }
     END         { print sqrt(sum / (n - 1)) }' "$1"

该 shell 脚本将首先使用上述average脚本来计算命令行上给出的文件中数据的平均值。该数字被分配给awk变量avg。然后,它使用与脚本相同类型的数字检测average来计算标准差。

由于这个脚本是现在编写的,因此它需要来自文件的数据,而不是标准输入的数据。


在数据上使用它的一种方法:

sed -n '/^<Score>/s///p' input.dat >output.dat

使用给定的数据,这将生成一个名为的文件,output.dat其中包含以下内容:

4
2
3

stdev在此文件上使用上面的脚本:

$ ./stdev output.dat
1

据我所知,这是正确的。


当然,您awk也可以直接在一次调用中完成此操作,而无需构建任何类型的可重用工具:

awk -F '>' '/^<Score>/ { v[++n] = $2; s += $2 }
            END { avg = s/n;
                  for (i=1; i<=n; ++i) {
                      std += (v[i] - avg)^2;
                  }
                  print sqrt(std / (n - 1));
                 }' input.dat

相关内容