多个文件的平均值和标准差

多个文件的平均值和标准差

我有 3000 个文件(1.out、2.out、3.out...,每个文件都有一个列,如下所示:

0.446477
0.439331
0.444394
0.425003
0.428981
0.419547
0.432834
0.417874
........

我需要计算 3000 个文件中每一行的平均值和标准差。我可以使用以下方法计算平均值:

awk '{a[FNR]+=$1;b[FNR]++;}END{for(i=1;i<=FNR;i++)print a[i]/b[i];}' *.out

但我坚持计算标准差。

答案1

复杂的解决方案使用粘贴命令和数据混合工具:

  1. 将所有文件合并为一个文件以进行进一步处理:

    paste [0-9]*.out | datamash transpose > data
    

    -- datamash transpose- 将行转置为列

  2. 获取字段总数:

    nf=`awk '{print NF; exit}' data`
    
  3. 计算平均值和标准差:

    for ((i=1; i<$nf; i++)); do datamash mean $i pstdev $i < data; done 
    

输出看起来像(第一列 - 平均值,第二列 - 标准偏差值):

0.596477    0.11180339887499
0.589331    0.11180339887499
0.594394    0.11180339887499
0.575003    0.11180339887499
0.578981    0.11180339887499
0.569547    0.11180339887499
0.582834    0.11180339887499
.......

答案2

标准差可以一次性计算出来无需过多修改您的脚本。

awk '{a[FNR]+=$1; b[FNR]++; c[FNR]+=$1*$1 } 
     END{
        for(i=1;i<=FNR;i++)
          print a[i]/b[i], sqrt((c[i]-a[i]*a[i]/b[i])/(b[i]-1)) ;
     }
' *.out

这是幼稚的实现,另一个实现,同一维基页面上的“在线方法”:

awk '{
  x=$1
  n[FNR] += 1
  delta = x - mean[FNR]
  mean[FNR] += delta/n[FNR]
  delta2 = x - mean[FNR]
  M2[FNR] += delta * delta2
}
END{
for(i=1;i<=FNR;i++)
        if(n[i]<2)
                print mean[i], 0
        else
                print mean[i], sqrt(M2[i]/(n[i]-1))
}' *.out

相关内容