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