Lissage par moyennes mobiles


Voici un tableau qui donne l'extension de la banquise au minimum de
septembre de 1979 à 2012 (source : NSIDC National Snow and Ice Data Center):

Année 79 80 81 82 83 84 85 86 87 88 89 90 91
Surface (km$^2$) 7.20 7.85 7.25 7.45 7.52 7.17 6.93 7.54 7.48 7.49 7.04 6.24 6.55
Année 92 93 94 95 96 97 98 99 00 01 02 03 04
Surface (km$^2$) 7.55 6.50 7.18 6.13 7.88 6.74 6.56 6.24 6.32 6.75 5.96 6.15 6.05
Année 05 06 07 08 09 10 11 12
Surface (km$^2$) 5.57 5.92 4.30 4.68 5.63 4.90 4.34 3.60



Voici une définition de la moyenne mobile d'ordre $k$ d'une telle série:



Définition : moyenne mobile
On appelle moyenne mobile d'ordre $k$ la moyenne arithmétique d'un terme avec les $k$ termes voisins.
- si $k$ est impair, c'est-à-dire s'écrit sous la forme $k=2p+1$ alors on remplace chaque terme par la moyenne de ce terme, des $p$ termes suivants et des $p$ termes précédents ;
- Si $k$ est pair, c'est-à-dire s'écrit sous la forme $k=2p$, c'est moins évident~:~on remplace chaque terme par la moyenne de ce terme, des $p$ termes suivants et des $p$ termes précédents mais les termes extrêmes sont affectés d'un coefficient 1/2.



Lisser une série chronologique c'est remplacer la série initiale par
la série des moyennes mobiles.

Par exemple, reprenons les données ci-dessus et effectuons
un lissage par moyennes mobiles d'ordre 5. Il y a 30 termes au
départ. L'ordre 5 étant impair, on va remplacer chaque terme par la
moyenne de ce terme, des 2 précédents et des deux suivants: on est donc
obligé de commencer par le troisième terme et de terminer par le
vingt-huitième.

On remplacera alors $t_3$
par $t'_3=\frac{t_1+t_2+t_3+t_4+t_5}{5}=\frac{5,3+5,5+4,95+5,13+5,37}{5}=5,25 $

Avec Python

On construit récursivement la liste des moyennes mobiles (dans le cas impair, c'est plus facile...).

Pour un rendu graphique d'une grande qualité, on utilise le module pygal de Python.

Ensuite, depuis ipython, on peut visualiser sur firefox par exemple, avec la commande !firefox ./banquise.svg

Python
def moyenne_mobile_impaire(y,k):
    def mobile(y,k,n):
        if n + k//2 >= len(y):
            return []
        else:
            return [sum(y[n - k//2 : n + 1 + k//2]) / k] + mobile(y,k,n + 1)
    return list(repeat(None,k//2)) + mobile(y,k,k//2)
 
 
donnees = [7.2, 7.85, 7.25, 7.45, 7.52, 7.17, 6.93, 7.54, 7.48, 7.49, 7.04, 6.24, 6.55, 7.55, 6.5, 7.18, 6.13, 7.88, 6.74, 6.56, 6.24, 6.32, 6.75, 5.96, 6.15, 6.05, 5.57, 5.92, 4.3, 4.68, 5.63, 4.9, 4.34, 3.6]
 
from pygal import *
 
banquise = Line(x_label_rotation=45)
 
banquise.title = "Évolution de la surface de la banquise au  minimum de septembre de 1979 à 2012 (source : National Snow and Ice Data Center)"
 
banquise.x_labels = list(map(str, range(1979, 2013)))
 
banquise.add("surface de la banquise au  minimum de septembre",donnees)
 
banquise.add("Moyenne mobile d'ordre 7", moyenne_mobile_impaire(donnees,7))
 
banquise.render_to_file("banquise.svg")
 
!firefox ./banquise.svg 

Voici le magnifique rendu SVG : n'hésitez pas à survoler les différentes parties de la page avec votre souris.

Avec xcas

Giac-XCAS
lmm(L,k):={
  X  := L[0];  Y := L[1];
  Xm := NULL; Ym := NULL;
  imax := size(X)-1;
  si k mod 2 == 0 alors
    p := k/2;
    pour j de p jusque imax-p faire
      Ym := Ym , (0.5*Y[j-p] + somme(Y[l],l,j-p+1,j+p-1) + 0.5*Y[j+p])/k;
      Xm := Xm , X[j];
    fpour; 
  sinon
    p := (k-1)/2;
    pour j de p jusque imax-p faire 
      Ym := Ym , (somme(evalf(Y[l]),l,j-p,j+p))/k;
      Xm := Xm , X[j];
    fpour;
  fsi;
  C :=  couleur(ligne_polygonale(X,Y),rouge):;
  Cm := couleur(ligne_polygonale([Xm],[Ym]),bleu):;
  retourne C,Cm }:;