média e desvio padrão de vários arquivos

1

Eu tenho 3000 arquivos (1.out, 2.out, 3.out ...., cada um com uma única coluna assim:

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

Preciso calcular média e desvio padrão para cada linha em 3000 arquivos. Eu poderia calcular a média usando:

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

Mas estou preso com o cálculo do desvio padrão.

    
por ashu 07.08.2017 / 06:39

2 respostas

2

Solução complexa usando o comando colar e ferramenta datamash :

  1. Mesclando todos os arquivos em um arquivo para processamento adicional:

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

    - datamash transpose - transporá as linhas para as colunas

  2. Obtendo o número total de campos:

    nf='awk '{print NF; exit}' data'
    
  3. Calculando a média e o desvio padrão:

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

A saída seria semelhante a (1ª coluna - valor médio, 2ª coluna - valor do desvio padrão):

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
.......
    
por 07.08.2017 / 09:56
1

O desvio padrão pode ser calculado em um passe sem modificar muito o seu script.

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

Esta é a implementação ingênua , outra implementação, o "método online" na mesma página da wiki:

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
    
por 07.08.2017 / 14:03