Flash Notes
Programmation - Ajustement de courbe : régression linéaire / exponentielle / logarithmique / puissance
• Comment programmer en AWK des fonctions d'ajustement de courbe (régression linéaire / exponentielle / logarithmique / puissance) ?
Solution
Voir ci-dessous ...
Programme
#!/bin/sh
#
# Ajustement de courbes
# ~~~~~~~~~~~~~~~~~~~~~
#
# lr : Linear Regression (Regression lineaire)
# ecf : Exponential Curve Fit (Ajustement de fonction exponentielle)
# lcf : Logarithmic Curve Fit (Ajustement de fonction logarithmique)
# pcf : Power Curve Fit (Ajustement de fonction puissance)
#
# Fonction d'affichage de l'usage
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
usage()
{
echo "Usage: $pgm_name data_file"
echo " cat data_file | $pgm_name"
echo " $pgm_name [-h|-help|--help]"
echo ""
echo "lr : Linear Regression : Regression lineaire"
echo "ecf : Exponential Curve Fit : Ajustement de fonction exponentielle"
echo "lcf : Logarithmic Curve Fit : Ajustement de fonction logarithmique"
echo "pcf : Power Cuve Fit : Ajustement de fonction puissance"
}
# Controle du nom du script
# ~~~~~~~~~~~~~~~~~~~~~~~~~
pgm_name=`basename $0`
case "$pgm_name" in
lr) FX=id ; FY=id ; FB=id ; FCT="y = a.x + b"
;;
ecf) FX=id ; FY=log ; FB=exp ; FCT="y = b.e^(a.x)"
;;
lcf) FX=log ; FY=id ; FB=id ; FCT="y = a.Log(x) + b"
;;
pcf) FX=log ; FY=log ; FB=exp ; FCT="y = b.x^a"
;;
*) echo "*** lr,ecf,lcf,pcf : nom $pgm_name inconnu"
usage
exit 1
;;
esac
# Controle des arguments
# ~~~~~~~~~~~~~~~~~~~~~~
case "$1" in
-h|-help|--help) usage
exit 1
;;
*) ;;
esac
if [ "$1" != "" ]
then
DATA_FILE="$1"
fi
awk 'BEGIN {
# Initialisation des variables
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
sum_x = 0;
sum_x2 = 0;
sum_y = 0;
sum_y2 = 0;
sum_xy = 0;
N = 0;
}
# Fonction identite
# ~~~~~~~~~~~~~~~~~
function id(x)
{
return x;
}
NF == 2 && $1 !~ /^[ ]*#/ {
x = '"$FX"'($1);
y = '"$FY"'($2);
sum_x += x;
sum_x2 += x*x;
sum_y += y;
sum_y2 += y*y;
sum_xy += x*y;
N++;
}
END {
a = (sum_xy - ((sum_x * sum_y)/N))/(sum_x2 -((sum_x^2)/N));
b = '"$FB"'((sum_y/N) - a*(sum_x/N));
r2 = ((sum_xy - ((sum_x*sum_y)/N))^2)/((sum_x2 - ((sum_x^2)/N))*(sum_y2 - ((sum_y^2)/N)));
printf("%s\n", "'"$FCT"'");
printf("a = %+f\n", a);
printf("b = %+f\n", b);
printf("r2 = %f\n", r2);
}' "$DATA_FILE"
Exemple 1
$ lr <<- EOF > 40.5 104.5 > 38.6 102 > 37.9 100 > 36.2 97.5 > 35.1 95.5 > 34.6 94 > EOF y = a.x + b a = +1.760149 b = +33.527130 r2 = 0.990946
Exemple 2
$ ecf <<- EOF 0.72 2.16 1.31 1.61 1.95 1.16 2.58 0.85 3.14 0.5 EOF y = b.e^(a.x) a = -0.582025 b = +3.445083 r2 = 0.980327
Exemple 3
$ lcf <<- EOF > 3 1.5 > 4 9.3 > 6 23.4 > 10 45.8 > 12 60.1 > EOF y = a.Log(x) + b a = +41.394468 b = -47.021198 r2 = 0.979834
Exemple 4
$ pcf <<- EOF > 10 0.95 > 12 1.05 > 15 1.25 > 17 1.41 > 20 1.73 > 22 2.00 > 25 2.53 > 27 2.98 > 30 3.85 > 32 4.59 > 35 6.02 > EOF y = b.x^a a = +1.455587 b = +0.026217 r2 = 0.935538