我编写了一个脚本,用于从数据文件中获取MEAN和STDEV。 假设数据文件包含以下数据:
1
2
3
4
5
awk脚本看起来像这样
awk '{MEAN+=$1/5}END{print MEAN, STDEV=sqrt(($1-MEAN)**2/4)}' dat.dat>stat1.dat
但它给了我一个不正确的STDEV值= 1。它必须是1.5811。你知道我的剧本中有什么不对吗?我怎么能改进它?
答案 0 :(得分:1)
请问您可以尝试关注并告诉我这是否对您有所帮助(这应该适用于提供的数据,如果您的实际文件也有更多字段)。
awk '{for(i=1;i<=NF;i++){sum+=$i};mean=sum?sum/NF:0;sum="";for(j=1;j<=NF;j++){$j=($j-mean)*($j-mean);sum+=$j};print "Mean=",mean", S.D=",sqrt(sum/NF)}' Input_file
现在也添加非单线形式的解决方案。
awk '
{
for(i=1;i<=NF;i++){ sum+=$i };
mean=sum?sum/NF:0;
sum="";
for(j=1;j<=NF;j++){ $j=($j-mean)*($j-mean);
sum+=$j};
print "Mean=",mean", S.D=",sqrt(sum/NF)
}
' Input_file
编辑: 添加类似于上面的代码只添加异常处理的类型,如果任何值为ZERO那么它应该打印0。
awk '
{
for(i=1;i<=NF;i++){ sum+=$i };
mean=sum?sum/NF:0
sum="";
for(j=1;j<=NF;j++){ $j=($j-mean)*($j-mean);
sum+=$j};
val=sum?sqrt(sum/NF):0
print "Mean=",mean", S.D=",val
}
' Input_file
答案 1 :(得分:1)
即使标题和标签说awk
,我想补充一点,使用datamash可以轻松完成计算一列数据的均值和stdev:
seq 1 5 | datamash mean 1 sstdev 1
3 1.5811388300842
这可能是偏离主题的(并且我意识到在awk
编写简单的任务可能是一个很好的学习机会),但我认为datamash
值得注意,特别是对于简单的计算比如这个。该文档提供了它可以执行的所有功能,以及包含许多列的文件的良好示例。这是一种快速可靠的替代方案。希望它有所帮助!
答案 2 :(得分:1)
你可以一次性做同样的事情
$ seq 5 | awk '{sum+=$1; sqsum+=$1^2}
END{mean=sum/NR;
print mean, sqrt((sqsum-NR*mean^2)/(NR-1))}'
3 1.58114
请注意,这是&#34;样本人口的标准定义&#34; (除以N-1)。
答案 3 :(得分:0)
这是一个两遍可流式版本:
parse.awk
# First-pass: sum the numbers
FNR == NR { sum += $1; next }
# After first pass: determine sample size (N) and mean
# Note: run only once because of the f flag
!f {
N = NR-1 # Number of samples
mean = sum/N # The mean of the samples
f = 1
}
# Second-pass: add the squares of the sample distance to mean
{ varsum += ($1 - mean)**2 }
END {
# Sample standard deviation
sstd = sqrt( varsum/(N-1) )
print "Sample std: " sstd
}
像这样运行文件:
awk -f parse.awk file.dat{,}
对于溪流运行它:
awk -f parse.awk <(seq 5) <(seq 5)
两种情况下的输出:
Sample std: 1.58114