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.