TD 3 : Régression linéaire simple et multiple

Régression linéaire simple

In [23]:
import pandas as pa
In [3]:
dic ={ 'CA' : [220, 280, 250, 170, 150, 340, 310, 210, 180, 190],
      'Frais' : [2.6, 2.6, 2.4, 1.5, 0.9, 3.0, 2.7, 2.3, 1.7, 1.9]}
df = pa.DataFrame(data=dic)
df.head()
Out[3]:
CA Frais
0 220 2.6
1 280 2.6
2 250 2.4
3 170 1.5
4 150 0.9
  1. Tracer le nuage de points et estimer le coefficient de corrélation linéaire.
In [24]:
import matplotlib.pyplot as plt
%matplotlib inline

figure, axes = plt.subplots()
axes.scatter(df['Frais'],df['CA'], color='r', marker='x')
axes.set_xlabel('Frais')
axes.set_ylabel('CA')
Out[24]:
Text(0, 0.5, 'CA')
In [7]:
from scipy.stats import pearsonr
X = df['Frais']
Y = df['CA']
coeff_pearson,_ = pearsonr(X,Y)
print("coefficient de Pearson = {}".format(coeff_pearson))
coefficient de Pearson = 0.8937577901007
In [20]:
#Plus simplement :
df.corr()
Out[20]:
CA Frais
CA 1.000000 0.893758
Frais 0.893758 1.000000

Les deux variables sont fortement corrélées

  1. Etablir la droite de régression correspondant à ce problème et tracer cette droite.
In [12]:
from scipy import stats
slope, intercept, r_value, p_value, _ = stats.linregress(X,Y)
Yhat = slope * X + intercept
print('(D) : Yhat = ',slope,' * X + ', intercept )
figure, axes = plt.subplots()
axes.scatter(X,Y, color='r', marker='x')
axes.scatter(X,Yhat, color='b', marker='o')
plt.plot(X,Yhat,c='m')
axes.set_xlabel('Frais')
axes.set_ylabel('CA')
(D) : Yhat =  87.40701381509031  * X +  41.20085015940495
Out[12]:
Text(0, 0.5, 'CA')
  1. Tester la significativité de la régression au risque 5%.

Le modèle que l'on cherche s'écrit : $$ CA = \beta_0 + \beta_1 Frais $$ On pose l'hypothèse :

$$ H_0 : \beta_1 = 0 $$
In [14]:
print('p_value = ', p_value)
p_value =  0.0004894341749604697

On observe que p_value << 5%.

$\Rightarrow$ On rejette donc $H_0$ au risue $5%$.

La régression est bien pertinenete.

  1. Calculer le coefficient de détermination.

Le facteur de détermination est de :

In [13]:
print('R^2 = ', r_value)
R^2 =  0.8937577901006998

$\Rightarrow$ 89% de la variation du CA est expliquées par les Frais

  1. Quel serait le chiffre d’affaires mensuel prédit par le modèle pour un budget publicitaire mensuel de 400 euros ? de 4000 euros ?
In [16]:
def predict(x):
    return slope * x + intercept

print('Le CA mensuel pour un budget publicitaire mensuel de 4OO € serait de : ', predict(400))
print('Le CA mensuel pour un budget publicitaire mensuel de 4OO0 € serait de : ', predict(4000))
Le CA mensuel pour un budget publicitaire mensuel de 4OO € serait de :  35004.006376195524
Le CA mensuel pour un budget publicitaire mensuel de 4OO0 € serait de :  349669.2561105206

Régression linéaire multiple

In [21]:
data = pa.read_csv('https://www.labri.fr/~zemmari/datasets/proprietes.csv',delimiter=';')
data.head()
Out[21]:
Valeur Totale Valeur Terrain Acre Pied2 Extérieur Chauffage Pièces Chambre SbainsC Sbains Foyers Garage
0 199657 63247 1,63 1726 Good NatGas 8 4 2 1 2 Garage
1 78482 38091 0,495 1184 Good NatGas 6 2 1 0 0 NoGarage
2 119962 37665 0,375 1014 Good Electric 7 3 2 0 1 Garage
3 116492 54062 0,981 1260 Average Electric 6 3 2 0 1 Garage
4 131263 61546 1,14 1314 Average NatGas 8 4 2 1 2 NoGarage
In [115]:
data.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 79 entries, 0 to 78
Data columns (total 12 columns):
Valeur Totale     79 non-null int64
Valeur Terrain    79 non-null int64
Acre              79 non-null object
Pied2             79 non-null int64
Extérieur         79 non-null object
Chauffage         79 non-null object
Pièces            79 non-null int64
Chambre           79 non-null int64
SbainsC           79 non-null int64
Sbains            79 non-null int64
Foyers            79 non-null int64
Garage            79 non-null object
dtypes: int64(8), object(4)
memory usage: 7.5+ KB

On voit qu'il n'y a pas de donnnées manquantes.

  1. Y a-t-il un lien entre la valeur totale et les différents facteurs ?
In [19]:
data.corr()
Out[19]:
Valeur Totale Valeur Terrain Pied2 Pièces Chambre SbainsC Sbains Foyers
Valeur Totale 1.000000 0.814685 0.766510 0.626500 0.582365 0.626234 0.435950 0.547980
Valeur Terrain 0.814685 1.000000 0.515980 0.517940 0.497388 0.505859 0.235842 0.496970
Pied2 0.766510 0.515980 1.000000 0.562823 0.431150 0.457476 0.353999 0.364592
Pièces 0.626500 0.517940 0.562823 1.000000 0.790934 0.479091 0.488519 0.394377
Chambre 0.582365 0.497388 0.431150 0.790934 1.000000 0.585968 0.166039 0.399628
SbainsC 0.626234 0.505859 0.457476 0.479091 0.585968 1.000000 0.171758 0.485582
Sbains 0.435950 0.235842 0.353999 0.488519 0.166039 0.171758 1.000000 0.385958
Foyers 0.547980 0.496970 0.364592 0.394377 0.399628 0.485582 0.385958 1.000000

Seule la première ligne de la matrice ci-dessus est intéressante pour nous.

On y voit que la valeur totale est corrélée avec toutes les autres variables. En effet, tous les facteurs se corrélation sont > 0.5 (sauf Sbains)

On peut aussi afficher les figures pour visualiser les données et voir s'il y a des liens :

In [32]:
X1 = data['Valeur Terrain']
X2 = data['Pied2']
X3 = data['Pièces']
X4 = data['Chambre']
X5 = data['SbainsC']
#X6 = data['Sbains']
X7 = data['Foyers']
Y = data['Valeur Totale']

axes = plt.subplot(2, 3, 1)

axes.scatter(X1,Y, color='r', marker='x')
axes.set_xlabel('Valeur Terrain')
axes.set_ylabel('Valeur Totale')

axes = plt.subplot(2, 3, 2)
axes.scatter(X2,Y, color='r', marker='x')
axes.set_xlabel('Pied2')
axes.set_ylabel('Valeur Totale')

axes = plt.subplot(2, 3, 3)
axes.scatter(X3,Y, color='r', marker='x')
axes.set_xlabel('Pièces')
axes.set_ylabel('Valeur Totale')

axes = plt.subplot(2, 3, 4)
axes.scatter(X4,Y, color='r', marker='x')
axes.set_xlabel('Chambre')
axes.set_ylabel('Valeur Totale')

axes = plt.subplot(2, 3, 5)
axes.scatter(X5,Y, color='r', marker='x')
axes.set_xlabel('SbainsC')
axes.set_ylabel('Valeur Totale')

axes = plt.subplot(2, 3, 6)
axes.scatter(X7,Y, color='r', marker='x')
axes.set_xlabel('Foyers')
axes.set_ylabel('Valeur Totale')
Out[32]:
Text(0, 0.5, 'Valeur Totale')
In [52]:
Y = data['Valeur Totale']
columns = ['Valeur Terrain','Pied2','Pièces','Chambre','SbainsC','Sbains','Foyers']

for j in range(len(columns)-1):
    axes = plt.subplot(2, 3, j+1)
    axes.scatter(data[columns[j]],Y, color='r', marker='x')
    axes.set_xlabel(columns[j])
    axes.set_ylabel('Valeur Totale')
range(0, 6)
In [116]:
Y = data['Valeur Totale']
columns = ['Valeur Terrain','Pied2','Pièces','Chambre','SbainsC','Sbains','Foyers']
couleurs = ['r', 'b', 'g', 'm', 'y', 'b', 'r', 'b']
figure = plt.figure(figsize=(20,10))
for j in range(len(columns)-1):
    axes = plt.subplot(2, 3, j+1)
    axes.scatter(data[columns[j]],Y, color=couleurs[j], marker='x')
    axes.set_xlabel(columns[j])
    axes.set_ylabel('Valeur Totale')
  1. Afficher les valeurs des différentes statistiques desciptives.
In [64]:
data.describe()
Out[64]:
Valeur Totale Valeur Terrain Pied2 Pièces Chambre SbainsC Sbains Foyers
count 79.000000 79.000000 79.000000 79.000000 79.000000 79.000000 79.000000 79.000000
mean 187253.405063 65899.481013 1677.911392 8.518987 3.987342 2.240506 0.721519 1.974684
std 84401.421337 22986.951385 634.638847 2.401179 1.265860 1.283177 0.714981 1.367898
min 74365.000000 35353.000000 672.000000 5.000000 2.000000 1.000000 0.000000 0.000000
25% 123089.000000 48002.000000 1147.000000 7.000000 3.000000 1.000000 0.000000 1.000000
50% 156761.000000 59861.000000 1628.000000 8.000000 4.000000 2.000000 1.000000 2.000000
75% 235277.500000 77868.000000 2022.000000 10.000000 5.000000 3.000000 1.000000 2.500000
max 453744.000000 131224.000000 3501.000000 18.000000 8.000000 7.000000 3.000000 7.000000
  1. Faites les différentes régressions linéaires simples possibles, et choisissez la (ou les) plus pertinente(s).
In [84]:
from scipy import stats
for j in range(len(columns)-1):
    slope, intercept, r_value, p_value, _ = stats.linregress(data[columns[j]],Y)
    print('Modèle ', j+1)
    print('------- Valeur Totale = ', intercept, ' + ', slope, ' * ', columns[j])
    print('------- R^2 = ', r_value)
    print('        Donc {:2.2f}% de la variabilité de la valeur totale est expliquée par {:s}'.format(
        r_value *100,columns[j]))
    print('------- p_value = ', p_value)   
    print('        H0: beta_1 = 0')
    if p_value < 0.05 :
        print('        ', p_value, '<= 5%', '==> on rejette H0, au risque alpha = 5%')
        print('         le modlèle ', j+1, ' est bien pertinent.')
    else:
        print('        ', p_value, '> 5%', '==> on accepte H0, au risque alpha = 5%')
        print('         le modlèle ', j+1, ' n''est pas pertinent car pas statistiquement significatif.')        
Modèle  1
------- Valeur Totale =  -9870.846451247635  +  2.9912868581874625  *  Valeur Terrain
------- R^2 =  0.8146849247133185
        Donc 81.47% de la variabilité de la valeur totale est expliquée par Valeur Terrain
------- p_value =  6.636865062557978e-20
        H0: beta_1 = 0
         6.636865062557978e-20 <= 5% ==> on rejette H0, au risque alpha = 5%
         le modlèle  1  est bien pertinent.
Modèle  2
------- Valeur Totale =  16208.538146922976  +  101.939153456249  *  Pied2
------- R^2 =  0.7665101583832423
        Donc 76.65% de la variabilité de la valeur totale est expliquée par Pied2
------- p_value =  1.8250569973875542e-16
        H0: beta_1 = 0
         1.8250569973875542e-16 <= 5% ==> on rejette H0, au risque alpha = 5%
         le modlèle  2  est bien pertinent.
Modèle  3
------- Valeur Totale =  -347.1329936950351  +  22021.459890790356  *  Pièces
------- R^2 =  0.6264997175170416
        Donc 62.65% de la variabilité de la valeur totale est expliquée par Pièces
------- p_value =  6.587283930995815e-10
        H0: beta_1 = 0
         6.587283930995815e-10 <= 5% ==> on rejette H0, au risque alpha = 5%
         le modlèle  3  est bien pertinent.
Modèle  4
------- Valeur Totale =  32427.76574843019  +  38829.287320234966  *  Chambre
------- R^2 =  0.582365144239742
        Donc 58.24% de la variabilité de la valeur totale est expliquée par Chambre
------- p_value =  1.802756854291162e-08
        H0: beta_1 = 0
         1.802756854291162e-08 <= 5% ==> on rejette H0, au risque alpha = 5%
         le modlèle  4  est bien pertinent.
Modèle  5
------- Valeur Totale =  94965.24039030158  +  41190.76276365071  *  SbainsC
------- R^2 =  0.6262340186658073
        Donc 62.62% de la variabilité de la valeur totale est expliquée par SbainsC
------- p_value =  6.730360516931453e-10
        H0: beta_1 = 0
         6.730360516931453e-10 <= 5% ==> on rejette H0, au risque alpha = 5%
         le modlèle  5  est bien pertinent.
Modèle  6
------- Valeur Totale =  150122.10476190475  +  51462.67936507937  *  Sbains
------- R^2 =  0.435950382739187
        Donc 43.60% de la variabilité de la valeur totale est expliquée par Sbains
------- p_value =  5.922307104773473e-05
        H0: beta_1 = 0
         5.922307104773473e-05 <= 5% ==> on rejette H0, au risque alpha = 5%
         le modlèle  6  est bien pertinent.

Si on doit choisir un modèle et un seul, le meilleur est le modèle 1.

  1. Faites la régression multiple de la Valeur totale en fonction des autres facteurs (quand c’est possible). Analysez les résultats obtenus.
In [112]:
Y = data['Valeur Totale']
X = data[columns]
In [86]:
from sklearn.linear_model import LinearRegression
model = LinearRegression()
model.fit(X, Y)
print(model.intercept_)
print(model.coef_)
-57009.08941780863
[ 1.77261832e+00  5.17288482e+01 -5.13570089e+03  1.16684396e+04
  8.59826844e+03  2.34912143e+04  8.41920181e+02]
In [106]:
print('Modèle de régression : ')
m = 'Valeur Totale = ' + str(model.intercept_) + ' + '
for i in range(len(model.coef_)-1):
    m =  m + str(model.coef_[i]) + ' * ' + columns[i] + ' + '
m = m + str(model.coef_[i+1]) + ' * ' + columns[i+1]
print(m)
Modèle de régression : 
Valeur Totale = -57009.08941780863 + 1.7726183178894592 * Valeur Terrain + 51.72884818587487 * Pied2 + -5135.700893311076 * Pièces + 11668.439578336624 * Chambre + 8598.268443611838 * SbainsC + 23491.21432644417 * Sbains + 841.9201808375863 * Foyers
In [107]:
import warnings
warnings.filterwarnings("ignore")

import numpy as np
from statsmodels.regression.linear_model import OLS
X['Ones'] = np.ones(len(Y))
m = OLS(Y,X)
results = m.fit()
su = results.summary()
su
Out[107]:
OLS Regression Results
Dep. Variable: Valeur Totale R-squared: 0.878
Model: OLS Adj. R-squared: 0.866
Method: Least Squares F-statistic: 72.95
Date: Fri, 18 Sep 2020 Prob (F-statistic): 6.98e-30
Time: 10:38:31 Log-Likelihood: -924.64
No. Observations: 79 AIC: 1865.
Df Residuals: 71 BIC: 1884.
Df Model: 7
Covariance Type: nonrobust
coef std err t P>|t| [0.025 0.975]
Valeur Terrain 1.7726 0.205 8.667 0.000 1.365 2.180
Pied2 51.7288 7.253 7.132 0.000 37.267 66.191
Pièces -5135.7009 3144.245 -1.633 0.107 -1.14e+04 1133.746
Chambre 1.167e+04 5484.263 2.128 0.037 733.131 2.26e+04
SbainsC 8598.2684 3735.359 2.302 0.024 1150.174 1.6e+04
Sbains 2.349e+04 6586.034 3.567 0.001 1.04e+04 3.66e+04
Foyers 841.9202 3312.750 0.254 0.800 -5763.516 7447.356
Ones -5.701e+04 1.41e+04 -4.030 0.000 -8.52e+04 -2.88e+04
Omnibus: 1.145 Durbin-Watson: 1.695
Prob(Omnibus): 0.564 Jarque-Bera (JB): 0.575
Skew: 0.011 Prob(JB): 0.750
Kurtosis: 3.417 Cond. No. 2.86e+05


Warnings:
[1] Standard Errors assume that the covariance matrix of the errors is correctly specified.
[2] The condition number is large, 2.86e+05. This might indicate that there are
strong multicollinearity or other numerical problems.

Analyse de la régression :

$R^2 = 0.878$ $\Rightarrow$ 88% de la variabilité de Valeur Totale est expliquée par les variables considérées.

On pose : $$ H_0 : \beta_1 = \beta_2 = \beta_3 = \beta_4 = \beta_5 = \beta_6 = \beta_7 = 0, $$ où $\beta_1, \beta_2, \beta_3, \beta_4, \beta_5, \beta_6, \beta_7$ correspondent aux coefficients de Valeur Terrain, Pied2, Pièces, Chambre, SbainsC, Sbains , et Foyers respectivement.

On observe que p_value = 6.98e-30, ce qui est très petit comparé seuil $\alpha = 5%$. On rejette donc $H_0$ et on considère que la variation de Valeur Totale est explicable par au moins une des autres variables.

Pour chacune des variables, on pose l'hypothèse : $$ H_0 : \beta_i = 0, $$ On analyse la deuxième partie du rapport de la régression. On voit que toutes les p_value, exeptées celles de Pièces et de Foyers sont < au seuil $5%$. On rejette donc toutes les hypothèses sauf celles concernant ces deux variables.

On refait la régression en éliminant les deux varaibles Pièces et Foyers :

In [113]:
X_cols = X.columns.drop(['Pièces', 'Foyers'])
print(X_cols)
X = X[X_cols]
m = OLS(Y,X)
results = m.fit()
su = results.summary()
su
Index(['Valeur Terrain', 'Pied2', 'Chambre', 'SbainsC', 'Sbains'], dtype='object')
Out[113]:
OLS Regression Results
Dep. Variable: Valeur Totale R-squared (uncentered): 0.972
Model: OLS Adj. R-squared (uncentered): 0.970
Method: Least Squares F-statistic: 514.5
Date: Fri, 18 Sep 2020 Prob (F-statistic): 5.70e-56
Time: 10:58:10 Log-Likelihood: -937.11
No. Observations: 79 AIC: 1884.
Df Residuals: 74 BIC: 1896.
Df Model: 5
Covariance Type: nonrobust
coef std err t P>|t| [0.025 0.975]
Valeur Terrain 1.4626 0.213 6.857 0.000 1.038 1.888
Pied2 39.5226 7.740 5.107 0.000 24.101 54.944
Chambre -3561.4896 3584.511 -0.994 0.324 -1.07e+04 3580.805
SbainsC 1.324e+04 4035.222 3.281 0.002 5198.538 2.13e+04
Sbains 1.867e+04 6016.310 3.103 0.003 6679.851 3.07e+04
Omnibus: 8.766 Durbin-Watson: 1.448
Prob(Omnibus): 0.012 Jarque-Bera (JB): 15.330
Skew: 0.310 Prob(JB): 0.000469
Kurtosis: 5.067 Cond. No. 1.05e+05


Warnings:
[1] Standard Errors assume that the covariance matrix of the errors is correctly specified.
[2] The condition number is large, 1.05e+05. This might indicate that there are
strong multicollinearity or other numerical problems.

La variable Chambre a un p_value > 5%. On l'élimine :

In [114]:
X_cols = X.columns.drop(['Chambre'])
X = X[X_cols]
m = OLS(Y,X)
results = m.fit()
su = results.summary()
su
Out[114]:
OLS Regression Results
Dep. Variable: Valeur Totale R-squared (uncentered): 0.972
Model: OLS Adj. R-squared (uncentered): 0.970
Method: Least Squares F-statistic: 643.0
Date: Fri, 18 Sep 2020 Prob (F-statistic): 3.44e-57
Time: 11:04:59 Log-Likelihood: -937.63
No. Observations: 79 AIC: 1883.
Df Residuals: 75 BIC: 1893.
Df Model: 4
Covariance Type: nonrobust
coef std err t P>|t| [0.025 0.975]
Valeur Terrain 1.3659 0.190 7.197 0.000 0.988 1.744
Pied2 37.1174 7.351 5.050 0.000 22.474 51.760
SbainsC 1.179e+04 3761.622 3.134 0.002 4295.007 1.93e+04
Sbains 1.872e+04 6015.569 3.112 0.003 6736.019 3.07e+04
Omnibus: 10.295 Durbin-Watson: 1.391
Prob(Omnibus): 0.006 Jarque-Bera (JB): 14.627
Skew: 0.526 Prob(JB): 0.000666
Kurtosis: 4.827 Cond. No. 1.05e+05


Warnings:
[1] Standard Errors assume that the covariance matrix of the errors is correctly specified.
[2] The condition number is large, 1.05e+05. This might indicate that there are
strong multicollinearity or other numerical problems.

La toutes les variables ont une p_value <= 5%. On garde donc ce modèle.

In [ ]: