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
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?
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
awk 'FNR==NR { file1[NR]=$1; next; }; { diff=$1-file1[FNR]; sum+=diff^2;};
END { print sum/FNR; }' file1 file2
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