batch/library/Metier/Scores/Regression.php

220 lines
6.7 KiB
PHP

<?php
class Metier_Scores_Regression
{
/*
But: Fournir un objet assez complet permettant d'opérer facilement une régression
linéaire, plus connu sur le nom de courbe de tendance sous Excel.
Usage: 0- Dans votre fichier PHP insérer include ("CrbTendance.php");
1- Déclarer l'objet RegLin
ex: $oReg= new RegLin($tDonnees) ou $oReg= new RegLin($tY, $tX)
Les deux syntaxe sont disponible, si une seul tableau est fourni
alors le second est initialisé du même nombre d'occurence commençant à 0
avec un pas de 1
2- Lancer le calcul, avec méthodes fournie de 0 à 4, par défaut 0 sera pris. Pour
tout élément supérieur à 4, la cinquième sera prise.
Cette méthode retourne un tableau à Trois positions,
-avec dans la case "A" le coef directeur de la droite,
-dans la case "B" le positionnement vertical
-dans la case "Cor" le coef de corrélation
-et dans la case "Meth" le numéro de la méthode utlisée
Ex: print_r($oReg0->OptMV(0));
==>Array ( [A] => -649.029426204
[B] => 3037796.68186
[Cor] => -0.143065138366
[Meth] => 0 )
3- De manière optionnel vous pouvez lancer la méthode GetOpt();,
qui vous fournira le point de votre droite en fonction de votre
tableau d'abscisses, si ce dernier n'est pas fourni
vous aurez un tableau de 0 à nb-1 d'occurence du premier tableau
Ex: print_r($oReg1->GetOpt());
==>Array ( [1] => 3037147.65243
[7] => 3033253.47587
[20] => 3024816.09333
[21] => 3024167.06391
[22] => 3023518.03448)
*/
//champ de l'objet
private $tDonnees;
private $tAbscisse;
private $vNbElt; //Nombre déléments des tableaux
private $vMoyX; //Moyenne des X
private $vMoyY; //Moyenne des Y
private $vSumXY;
private $vSumX;
private $vSumY;
private $vSumX2;
private $tPtG; //Le point moyen G est un tableau tPtG(X,Y)=(vMoyX,vMoyY)
//La variance, c'est la moyenne des carrés soustrait du carré de la moyenne
private $vVarianceX;
private $vVarianceY;
//L'écart Type, c'est la racine carrée de la variance
private $vEcartTX;
private $vEcartTY;
//La covariance, la moyenne des produits moins le produit des moyennes
private $vCovariance;
private $vA; //Coef directeur de la droite liée à la régression
private $vB; //Coef B de la droite liée à la régression
public $vCoefCorLin;//Coef de corrélation linéaire
public $tTest;
public function __construct($tDataY,$tDataX=NULL)
{
$this->tDonnees = $tDataY;
$this->tAbscisse = $tDataX;
$this->vNbElt = $n=count($this->tDonnees); // Nombres d'éléments
//Mise en place des abscisses
if (isset($tDataX))
for($i=0;$i<$this->vNbElt;$i++)
$this->tAbscisse[$i]=$i;
//parcours des donnees pour récupération formule nécessaire au calcul des éléments
$sumX=0; //somme des X
$sumY=0; //somme des Y
$sumX2=0; //somme des X²
$sumY2=0; //somme des y²
$sumXY=0; //somme des x*y
for ($i=0;$i<$n;$i++) {
$xVal=$this->tAbscisse[$i];
$yVal=$this->tDonnees[$i];
$sumX+=$xVal;
$sumY+=$yVal;
$sumX2+=$xVal*$xVal;
$sumY2+=$yVal*$yVal;
$sumXY+=$xVal*$yVal;
}
$this->vMoyX=$sumX/$n; //moyenne X
$this->vMoyY=$sumY/$n; //moyenne Y
$this->vSumXY=$sumXY;
$this->vSumX=$sumX;
$this->vSumY=$sumY;
$this->vSumX2=$sumX2;
$this->tPtG=array('X'=>$this->vMoyX,'Y'=>$this->vMoyY); //point moyen G
//La variance, c'est la moyenne des carrés soustrait du carré de la moyenne: Rappel
$this->vVarianceX=($sumX2/$n)-($this->vMoyX*$this->vMoyX);
$this->vVarianceY=($sumY2/$n)-($this->vMoyY*$this->vMoyY);
//L'écart Type, c'est la racine carrée de la variance: Rappel
$this->vEcartTX=sqrt(abs($this->vVarianceX));
$this->vEcartTY=sqrt(abs($this->vVarianceY));
//La covariance, la moyenne des produits moins le produit des moyennes
$this->vCovariance=($sumXY/$n)-($this->vMoyX*$this->vMoyY);
// coef de coorélation linéaire: Covariance que divise l'écart Type X multiplié par l'écart Type de Y
$this->vCoefCorLin=$this->vCovariance/($this->vEcartTX*$this->vEcartTY);
// Calcul de la droite
$this->CoefsDroite(0);
$this->tTest=array(
'vMoyX'=>$this->vMoyX,
'vMoyY'=>$this->vMoyY,
'vA'=>$this->vA, // Coef directeur de la droite liée à la régression
'vB'=>$this->vB, // Coef B de la droite liée à la régression
'tPtG'=>$this->tPtG,
'vVarianceX'=>$this->vVarianceX,
'vVarianceY'=>$this->vVarianceY,
'vEcartTX'=>$this->vEcartTX,
'vEcartTY'=>$this->vEcartTY,
'vCovariance'=>$this->vCovariance,
'vCoefCorLin'=>$this->vCoefCorLin,
);
}
/**
* Calcul de la droite
* (calcul de coef directeur de la régression par théorie de la régression linéaire
* le coef a est obtenu des manières suivantes avec 5 variantes disponibles)
*/
private function CoefsDroite($met=0)
{
switch ($met) {
case 0:
$this->vA=$this->vCovariance/$this->vVarianceX;
break;
case 1:
$this->vA=$this->vVarianceY/$this->vCovariance;
break;
case 2:
$this->vA=($this->vCovariance*$this->vEcartTY)/(abs($this->vCovariance)*$this->vEcartTX);
break;
/*
case 4:
$this->vA=($this->vSumXY-(($this->vSumX*$this->vSumY)/$this->vNbElt)/($this->vSumX2-(pow(2,$this->vSumX)/$this->vNbElt)));
break; */
case 3:
$this->vA=($this->vVarianceY-$this->vVarianceX+sqrt(pow($this->vVarianceY-$this->vVarianceX,2)+pow(2*$this->vCovariance,2)))/(2*$this->vCovariance);
break;
case 4:
$this->vA=($this->vSumXY-($this->vSumX*$this->vSumY/$this->vNbElt))/($this->vSumX2-(pow($this->vSumX,2)/$this->vNbElt));
break;
}
$this->vB=$this->vMoyY-($this->vA*$this->vMoyX);
}
/**
* Calcul la régression Linéaire
*/
public function OptMV($meth=0)
{
$this->CoefsDroite($meth);
$this->CoefCorLin();
return array("A"=>$this->vA,"B"=>$this->vB,"Cor"=>$this->vCoefCorLin,"Meth"=>$meth,"TauxProg"=>(1-$this->vA)*100);
}
/**
* Renvoi le tableau des points optimisés
*/
public function GetOpt()
{
$tOpt=array();
foreach($this->tAbscisse as $i)
$tOpt[$i]=$this->vA*$i+$this->vB;
return $tOpt;
}
public function GetProjection($nbPeriodes)
{
$iMax=end($this->tAbscisse)+$nbPeriodes+1;
$tOpt=array();
for ($i=end($this->tAbscisse); $i<$iMax; $i++)
$tOpt[$i]=$this->vA*$i+$this->vB;
return $tOpt;
}
public function GetProjectionDebut($nbPeriodes)
{
$iMax=end($this->tAbscisse)+$nbPeriodes+1;
$tOpt=array();
reset($this->tAbscisse);
for ($i=current($this->tAbscisse); $i<$iMax; $i++)
$tOpt[$i]=$this->vA*$i+$this->vB;
return $tOpt;
}
public function TauxProgression($nbPeriodes)
{
$tOpt=$this->GetProjection($nbPeriodes);
reset($tOpt);
//print_r($tOpt);
$deb=abs(current($tOpt));
$fin=abs(end($tOpt));
return (($fin-$deb)*100)/$deb;
}
}