5.1. Base du traitement de données#
Marc BUFFAT, dpt mécanique, Université Lyon 1

%matplotlib inline
import numpy as np
import matplotlib.pyplot as plt
from validation.valide_markdown import test_markdown
# utilisation de taille de caractère plus grande
plt.rc('font', family='serif', size='16')
5.1.1. Objectifs#
Apprendre à lire des données dans un fichier, les analyser et les traiter pour en déduire des prédictions.
La démarche consiste en
lecture des données
analyse des données
détermination d’une loi simple
prédiction à partir de cette loi
analyse des résultats
application
problème du réchauffement climatique.

5.1.2. Compte rendu#
éditer le fichier
CompteRendu.md
, puis génerer la sortie html avec la commande ci-dessousvisualiser le fichier
CompteRendu.html
# génération de la version html et pdf du CR
!genereTPhtml CompteRendu
5.1.3. Lecture des données#
notion de fichier
fichier = espace sur disque (ou sur un serveur) permettant de stocker de l’information
nom du fichier fichier
dossier ou se trouve le fichier
type de fichier (texte, binaire, ..)
format des données (formats ouverts (csv) ou propriétaire (excel))
lecture des données stockées dans un fichier
il faut connaître comment sont stockées les données (format standard)
si stockage simple par colonne, utilisation de la fonction numpy
loadtxt
affichage des données brutes
Traitement d’un exemple
analyse de la position X(t) mesurée (en m.) en fonction du temps t (en s.)
données dans un fichier
data.txt
dans le répertoiredata
# generation des données
_N = 25
_X = np.linspace(0,2,_N)
_Y = 2*_X + 0.5*(1-2*np.random.rand(_N)) - 1.0
np.savetxt("data/data.txt",np.array([_X,_Y]).transpose())
# affichage des données
!head "data/data.txt"
0.000000000000000000e+00 -1.361032483838930940e+00
8.333333333333332871e-02 -9.379920530064309592e-01
1.666666666666666574e-01 -1.078092419852459738e+00
2.500000000000000000e-01 -6.988714289891271303e-01
3.333333333333333148e-01 9.524923911012228572e-03
4.166666666666666297e-01 -6.591635405968687689e-01
5.000000000000000000e-01 -2.086777686492905515e-01
5.833333333333332593e-01 5.326231932802212299e-01
6.666666666666666297e-01 4.709120098674191013e-01
7.500000000000000000e-01 9.926747043680661520e-02
# lecture et tracer des données
### BEGIN SOLUTION
T,X = np.loadtxt("data/data.txt",unpack=True)
plt.plot(T,X,'o')
#plt.figure(figsize=(10,6))
#plt.plot(T,X,'o')
#plt.xlabel("t [en s.]")
#plt.ylabel(" x [en m]")
#plt.title("Position en fonction du temps");
### END SOLUTION
[<matplotlib.lines.Line2D at 0x7f3412f77040>]

T,X = np.loadtxt("data/data.txt",unpack=True)
plt.plot(T,X)
[<matplotlib.lines.Line2D at 0x7f3410e82860>]

5.1.4. Analyse des données#
valeurs moyenne, min et max
écriture d’une fonction pour calculer la moyenne, le min et le max d’un tableau numpy
5.1.4.1. Algorithme#
Soit X un tableau de n valeurs
definition algorithme d’analyse
Algorithme Analyse(Tab)
""" analyse d'un tableau Tab: renvoie la moyenne, le min et le max """
n = taille(X)
Tmin = Tab[0]
Tmax = Tab[0]
Tmean = 0.
pour chaque valeur val du tableau Tab
Tmean = Tmean + val
Tmax = max(val, Tmax)
Tmin = min(val, Tmin)
fin pour
Tmean = Tmean / n
retour Tmean, Tmin, Tmax
5.1.4.2. Programmation fonction python#
écriture d’une fonction Python:
def Analyse(Tab):
validation
on choisit la fonction linaire x entre a et b \(\leadsto\) min=a max=b mean =(a+b)/2
Y = np.linspace(debut,fin,11) Analyse(Y) -> (debut+fin)/2, debut, fin
### BEGIN SOLUTION
def Analyse(Tab):
n = Tab.size
Tmin = Tab[0]
Tmax = Tab[0]
Tmean = 0.
for val in Tab:
Tmean += val
Tmin = min(Tmin,val)
Tmax = max(Tmax,val)
return Tmean/n, Tmin, Tmax
# verification
print("resultat 2,1,3: ",Analyse(np.linspace(1.,3.,11)))
### END SOLUTION
resultat 2,1,3: (2.0, 1.0, 3.0)
# application pour l'analyse des données
### BEGIN SOLUTION
tmean, tmin, tmax = Analyse(T)
print("données en temps: moyenne={}s \t min={}s \t max={}s ".format(tmean, tmin, tmax))
xmean, xmin, xmax = Analyse(X)
print("données en espace: moyenne={:.2f}m \t min={:.2f}m \t max={:.2f}m ".format(xmean, xmin, xmax))
### END SOLUTION
données en temps: moyenne=1.0s min=0.0s max=2.0s
données en espace: moyenne=0.90m min=-1.36m max=3.21m
5.1.5. Détermination d’une loi simple: lissage des données#
Afin d’avoir une idée du comportement général des données, nous allons chercher une courbe lisse qui correspond (approximativement) aux points de mesure. Nous recherchons une courbe simple (par exemple, un polynôme de degré m) qui permet de lisser le bruit toujours présent dans les données expérimentales.
5.1.5.1. régression par moindres carrés#
Soit \(f (x)\) la fonction que nous ajusterons aux \(n+1\) points expérimentaux: \( (x_i, y_i) \), \( i = 0, 1, ..., n \):
La fonction dépend de \(m+1\) paramêtres \(a_0, ...,a_m\) avec \(m<n\) $\( f (x) = f (x; a_0, a_1, ..., a_m) \)$
Nous devons choisir la forme de \( f (x) \) à priori, en inspectant les données expérimentales et en utilisant notre connaissance du phénomène étudié. Ainsi, l’ajustement de courbe se compose de deux étapes:
Choisir la forme de \( f (x) \), par exemple un polynôme de degré 1: $\( f(x) = a_0 + a_1 x \)$
Calculer les paramètres \(a_k\) qui donneront la « meilleure approximation » par rapport aux données.
5.1.5.2. un peu de thèorie#
Lorsque les oordonnées \(y\) des points de données sont bruitées, il est courant d’utiliser un lissage par moindres carrés, qui consiste à minimiser l’erreur quadratique \(Err\) entre la fonction de lissage \(f\) et les points de mesure:
par rapport à chacun des paramètres \( a_j \). La valeur des paramètres est obtenue en écrivant la condition de minimisation
qui traduisent la condition de minimisation d’annulation du gradient \(\vec{\nabla} Err = \vec{0}\)
Les termes \( r_i = y_i - f (x_i) \) sont appelés résidus: ils donnent l’écart en \( x_i \) entre les données et la fonction de lissage. L’expression à minimiser est donc la somme des carrés des résidus.
5.1.5.3. Régression linéaire#
La fonction de lissage la plus simple est la régression linéaire, qui ajuste une ligne droite aux données. Dans ce cas,
La fonction à minimiser (somme des distances au carré) s’écrit:
Les équations de minimisation de \(Err\) deviennent:
et
Divisons les deux équations par \( 2 (n + 1) \) et réorganisons les termes.
Réorganisation de ces équations:
soit $\( a_0 = \bar {y} - a_1 \bar {x} \label{eq4} \)$
où \(\bar{x} = \frac{\sum_{i = 0}^{n} x_i}{n + 1}\) et \(\bar{y} = \frac{\sum_{i = 0}^{ n} y_i} {n + 1}\) sont respectivement la moyenne des \(\left( x_i \right)\) et des \(\left( y_i \right)\)
Réorganisation de ces équations:
Maintenant, si nous remplaçons \(a_0\) de la première équation dans la seconde et réorganisons les termes:
En remplaçant les définitions des valeurs moyennes dans l’équation,
En remplaçant \(\frac{\sum_{i = 0}^{n} x_i}{n + 1} = \bar{x}\),
en mettant les termes en \( a_1 \) à gauche:
on obtiens la valeur de \(a_1\):
D’où l’expression des coefficients \(a_1\) et \(a_0\) sont:
que l’on peut écrire sous la forme de moyenne uniquement
5.1.5.4. application au cas traité#
étapes:
programmation en réutilisant le code (utilisation de fonctions)
vérification en traçant et comparant le lissage avec les points de mesure
prédiction de la position à l’instant t=2.5 s
# application
### BEGIN SOLUTION
xtmean = Analyse(X*T)[0]
ttmean = Analyse(T*T)[0]
a1 = (xtmean -xmean*tmean)/(ttmean - tmean**2)
a0 = xmean - a1*tmean
print("loi x = {:.2f} + {:.2f} t".format(a0,a1))
t1 = 2.5
print("position a t={:.2f} x={:.2f}".format(t1,a0+a1*t1))
plt.figure(figsize=(10,6))
plt.plot(T,X,'o')
plt.plot(T,a0+a1*T,lw=2,label="lissage")
plt.plot([tmean],[xmean],'v',label="moyenne")
plt.plot([t1],[a0+a1*t1],'s',label="prediction")
plt.xlabel("t [en s.]")
plt.ylabel("x [en m]")
plt.legend()
plt.title("lissage moindres carrées");
### END SOLUTION
loi x = -1.14 + 2.04 t
position a t=2.50 x=3.96

Analyse du résultat
vérification:
ce n’est pas de l’interpolation (la courbe ne passe pas par tous les points)
mais la droite passe au voisinage de tous les points
la moyenne est sur la droite des moindres carrés
5.1.6. Application en TP: évolution de la température de la Terre#
Analyse des données d’évolution de la température de la Terre au cours du temps.
Les questions adressées, qui sont brûlante dans le monde d’aujourd’hui, sont:
La température de la terre augmente-t-elle?
Et de combien?
Les données sur l’évolution de la température terrestre sont disponibles à partir de plusieurs sources: la NASA, le National Climatic Data Center (NCDC) et l’Université d’East Anglia au Royaume-Uni. Consultez le site de University Corporation for Atmospheric Research (UCAR) pour une discussion approfondie.
Le NASA Goddard Space Flight Center est l’une des sources de données climatiques mondiales. Ils ont produit la vidéo ci-dessous montrant une carte en couleur de l’évolution de la surface globale anomalies de température de 1880 à 2015.
Le terme anomalie de température globale désigne la différence de température par rapport à une valeur de référence ou à une moyenne à long terme. C’est une manière très utile de regarder le problème et à bien des égards meilleur que la température absolue. Par exemple, un mois d’hiver peut être plus froid que la moyenne à Paris, ainsi qu’à Nice, mais les températures absolues seront différentes aux deux endroits.
# video sur l'evolution de la température
from IPython.display import YouTubeVideo
YouTubeVideo('gGOzHVUQCw0')
5.1.6.1. Méthode d’analyse#
La première étape dans l’analyse de données consiste à générer des graphiques simples en utilisant Matplotlib. Nous allons regarder l’historique des anomalies de température, contenu dans un fichier, et faire notre premier tracé pour explorer ces données.
Ensuite nous allons lisser les données, puis nous les ajusterons avec une droite pour déterminer une tendance en utilisant une loi simple.
A partir de cette loi simple, on va pouvoir en déduire une prédiction, qui est l’objectif final de l’étude.
5.1.6.2. définition des données#
Les données sont issues de la page Web NOAA (National Oceanic and Atmospheric Administration). Nous avons utilisé des données entre 1880 et aujourd’hui, mais vous pouvez utiliser des données actualisées à partir de ce même site.
Dans le répertoire data
, nous avons un fichier nommé anomalie_temperature.csv
. Ce fichier contient l’année sur la première colonne, et les moyennes des anomalies de température du sol répertoriées séquentiellement sur la deuxième colonne, à partir de 1880 jusqu’à nos jours. Nous allons charger le fichier, puis faire un premier tracé pour voir à quoi il ressemble.
En utilisant la commande unix/linux head mon_fichier
, on affiche les 10 premières lignes du fichier mon_fichier
Attention vous n’avez pas tous les mêmes données, donc ne vous contentez pas de comparer les résultats bruts, mais essayer de comprendre la méthode.
5.1.6.3. lecture du fichier#
Pour charger les données à partir du fichier, nous utiliserons la fonction numpy.loadtxt()
, qui nous permet de sauvegarder directement les données lues dans des tableaux NumPy. (
Les données sont séparées par des ,
et on veut enregistrer directement les données dans les deux tableaux annee
et anomalie_temp
. On va donc fournir des arguments à la fonction np.loadtxt
pour l’utiliser (voir la documentation de loadtxt)
annee, anomalie_temp = np.loadtxt(fichier, delimiter=',', unpack=True)
Dans la cellule suivante, écrire le code python pour lire les données dans les deux tableaux annee
et anomalie_temp
On aussi importer la bibliothèque numpy
5.1.6.4. lissage des données#
Nous allons lisser les données d’anomalie de température par une droite, pour en déduire l’évolution de la température terrestre. Nous utiliserons la régression linéaire par moindres carrés pour calculer la pente \(a_1\) et la constante \(a_0\)
avec pour expression des coefficients \(a_1\) et \(a_0\):
Dans notre cas, les données x
sont dans le tableau annee
, et les données y
sont dans le tableau anomalie_temp
.
5.1.6.5. programmation#
Pour calculer nos coefficients avec la formule ci-dessus, nous avons besoin des valeurs moyennes des données. Comme nous devons calculer la moyenne à la fois pour x
ety
, il est utile d’écrire une fonction Python personnalisée qui calcule la moyenne pour n’importe quel tableau, que l’on peut ensuite réutiliser.
C’est une bonne pratique de programmation d” éviter de répéter les instructions et d’écrire du code qui soit réutilisable, non seulement parce qu’il conduit à moins de temps de développement, mais aussi parce qu’il réduit les erreurs. Si vous devez faire le même calcul plusieurs fois, il vaut mieux l’encapsuler dans une fonction.
Rappelez-vous un des concepts clé de la programmation que l’on a vu ensemble:
Une fonction est une collection compacte de code qui exécute une action sur ses arguments ou données et qui renvoie le résultat.
Une fois défini, vous pouvez appeler une fonction autant de fois que vous le souhaitez. Lorsque nous appelons une fonction, nous exécutons tout le code à l’intérieur de la fonction. Le résultat de l’exécution dépend de la définition de la fonction et des valeurs qui y sont passées en arguments. Les fonctions peuvent ou non renvoyer des valeurs lors de leur dernière opération.
La syntaxe pour définir ses propres fonctions est la suivante:
def nom_fonction (arg_1, arg_2, ...):
'''
docstring: description de la fonction
'''
<corps de la fonction>
return valeur
Le docstring d’une fonction est un message du programmeur documentant ce qu’il a construit. Les docstrings
doivent être descriptifs et concis. Ils sont importants car ils expliquent (ou rappellent) l’utilisation prévue de la fonction aux utilisateurs. Vous pouvez accéder ultérieurement à la docstring d’une fonction en utilisant la fonction help ()
et en passant le nom de la fonction. Si vous êtes dans un notebook, vous pouvez également ajouter un point d’interrogation ?
avant le nom de la fonction et exécuter la cellule pour afficher les informations d’une fonction.
Vous aurez donc à écrire une fonction Moyenne(tableau)
qui calcule la valeur d’un tableau passé comme argument:
def Moyenne(tableau):
'''
calcule la moyenne arithmétique du tableau passé en argument
'''
<calcul de la moyenne>
return moyenne
5.1.7. Génération du compte rendu (version html)#
# génération de la version html et pdf du CR
!genereTPhtml CompteRendu
# test compte rendu
test_markdown("CompteRendu.md",None,100,0.8)
Erreur commentaire insuffisant (27)!
False