Test de Durbin-Watson
en langage python
L'essentiel de cette page.
Le test de Durbin-Watson permet de vérifier s'il n'y a pas des phénomènes d'autocorrélations. C'est à dire que les valeurs de x seraient corrélées par exemple au valeur x+7, phénomène typique dans les suite chronologiques avec une cyclicité.
Le test de Durbin permet ainsi de comprendre qu'une régression linéaire sur l'ensemble des valeurs est peut-être trop simpliste et qu'il faut envisager des sous-catégories (tels les jours de la semaine) qui se comporteraient chacun individuellement différement des autres, même si l'ensemble semble linéaire.
0- Simulons d'abord des données présentant une autocorrélation
Prenons un exemple : nous allons simuler le revenu quotidien d'une épicerie en fonction du temps. Cette épicerie augmente son chiffre d'affaire avec le temps et souhaite modéliser et prédire sa future augmentation de chiffre d'affaire.
Il y a toutefois un hic... Si le chiffre d'affaire augmente, il y a peut-être une différence entre les jours de la semaine. Certains augmente peut-être tandis que d'autres stagnent. Après tout, certains jours de la semaine sont toujours plus déterminants que d'autres dans le monde du commerce.
Code à copier-coller pour simuler les données :
jours = ["L","M","M","J","V","S","D"] # Jours de la semaine
rev_mean_jour = [1900,2000,4500,2000,1200,3048,1500] # Revenu moyen initial
rev_sd_jour = [400,400,500,400,300,300,200] # SD initial des revenus
rev_evol_jour = [1,1,1.1,1,1,1.1,0.9] # Coefficients d'évolution des jours
jour = list(range(70)) #Etude/simulation sur 70 jours
from numpy.random import normal as norm
effet_saison = ((np.sin([j/40 for j in jour])+1.8)/2+norm(0.6,0.1,1)-1)*4 # Coefficient d'augmentation en fonction du temps
# Simulations des revenus au jour le jour sur 70 jours
revenu = []
for j in jour :
temp = norm(loc=rev_mean_jour[(j%7)],size=1,scale=rev_sd_jour[(j%7)])
temp = np.array(temp*rev_evol_jour[j%7]*j/7)
#print(temp)
saison = np.array([effet_saison[j]])
#print(saison)
temp = temp * saison
#print("temp")
revenu = revenu + list(temp)
Code pour générer le graphique :
import matplotlib.pyplot as plt
plt.scatter(jour,revenu)
x_s, y_s = smooth(jour,revenu,box_percent=0.3) # fonction disponible ici
plt.plot(x_s,y_s, 'g-', lw=2)
plt.show()
1- Réalisons maintenant un modèle de régression linéaire avec tester avec le test de Durbin-Watson
Le modèle de régression
import pandas as pd
compil = pd.DataFrame(jour,revenu)
import statsmodels.formula.api as sm
model = sm.ols(formula='revenu ~ jour',data=compil)
myreg = model.fit()
Le grahique ACF d'auto-corrélation :
from statsmodels.graphics.tsaplots import plot_acf
plot_acf(myreg.resid)
plt.show()
Ce graphique permet de voir ce que le test de Durbin-Watson va démontrer : il existe une autocorrélation entre chaqu point N et le point N+7 ou N+14 (sortie de la zone bleue). Normale ! Tous les samedis rapportent plus ici et n'ont pas la même courbe de progression.
Le test de Durbin-Watson
from statsmodels.stats.stattools import durbin_watson
# Durbin-Watson test
print(durbin_watson(myreg.resid))
S'il n'y a pas d'autocorrélation, la valeur doit être centré autour de 2.
Plus on se rapproche de 0, plus les autocorrélations sont négatives.
Plus on se rapproche de 4, plus les autocorrélations sont positives.
On peut admettre de rejeter les autocorrélations si la valeur rendue est entre 1.5 et 2.5.
Ici, nous sommes à 2.45. Cela montre bien qu'on peut se montrer plus ou moins exigeant. En se fixant par exemple un bornage entre 1.8 et 2.2 par exemple.
Réellement, il existe des tables de ces valeurs. Le test pourrait donc renvoyer une p-value. Espérons qu'il sera amélioré à l'avenir pour rejoindre celui disponible sous R.