calcula a soma dos quadrados usando o shell script em perl / awk

3

Eu tenho 2 arquivos como abaixo.

file1

0.34
0.27
0.32

file2

0.15
0.21
0.15

Agora, gostaria de calcular a soma dos quadrados entre cada coluna. Por exemplo,

[(0.34 - 0.15)^2 + (0.27 - 0.21)^2 + (0.32 - 0.15)^2 ] / 3

Onde 3 é o número total de linhas no arquivo. Eu estarei tendo o mesmo número de linhas em ambos os arquivos.

Eu criei o script bash abaixo, que funciona perfeitamente, mas eu quero saber se existe alguma outra maneira mais fácil.

#! /bin/bash   
sum=0.0
while true; do
  read -r lineA <&3
  read -r lineB <&4
  if [ -z "$lineA" -o -z "$lineB" ]; then
    break
  fi
diff=$(bc <<< "scale=5; $lineA - $lineB")
square=$(bc <<< "scale=5; $diff*$diff")
sum=$(bc <<< "scale=5; $sum+$square")
done 3<file1 4<file2
filelen='wc -l file1 | cut -f1 -d' ''
final=$(bc <<< "scale=5; $sum/$filelen")
echo "$final"

Existe uma maneira mais simples em awk ou perl ?

EDITAR

Eu tinha 2 milhões de linhas no meu arquivo de entrada e o arquivo de entrada realmente continha números científicos, como abaixo.

3.59564e-185

Meu script, assim como as respostas sugeridas, falharam em números científicos. No entanto, eu poderia fazer meu script no trabalho de pergunta quando eu mudei os números científicos para 10^ notação.

Eu converti meu arquivo de entrada como abaixo.

sed -e 's/[eE]+*/\*10\^/' file1 > file1_converted
sed -e 's/[eE]+*/\*10\^/' file2 > file2_converted

Agora, as duas respostas sugeridas não deram a mensagem de erro Nan . Meu script pareceu funcionar, mas para 2 milhões de linhas, está demorando muito para ser executado.

Existe alguma maneira eficiente de fazer isso funcionar?

    
por Ramesh 01.07.2014 / 00:28

3 respostas

7

Uma maneira de fazer isso usando paste , já que seus arquivos têm o mesmo número de linhas.

paste file1 file2 | awk '{s += ($1-$2)^2}; END{print (s+0)/NR}'
0.0228667
    
por 01.07.2014 / 00:54
4
awk 'FNR==NR { file1[NR]=$1; next; }; { diff=$1-file1[FNR]; sum+=diff^2;}; 
  END { print sum/FNR; }' file1 file2
    
por 01.07.2014 / 01:12
1

Com seus grandes dados flutuantes, você pode usar perl com seu bignum :

$ paste file1 file2 | perl -Mbignum -anle '
    $sum += ($F[0] - $F[1])**2;
    END {     
        print $sum/$.;
    }                
'
0.02286666666666666666666666666666666666667
    
por 01.07.2014 / 21:09

Tags