logo

Licence L1, Université Lyon 1

Introduction à Python

Consignes pour les étudiants

  1. Exécution

Exécuter toujours tout le notebook depuis le début (en appuyant sur le bouton Executer ou Run). En effet un notebook est un programme et pas une simple page HTML qui doit s'exécuter dans l'ordre du début à la fin.

  1. Entrez du code

Les cellules de code dans lesquelles vous devez rentrer votre code contiennent les instructions suivantes, que vous devez supprimer et remplacer par votre réponse.

    # YOUR CODE HERE
    raise NotImplementedError()

En générale, ces cellules sont suivies par une cellule de validation que vous devez exécuter et qui permet de détecter des erreurs.

ATTENTION ces tests unitaires permettent de détecter certaines erreurs mais pas toutes, et donc ne garantissent pas que le code que vous rentrez est $100\%$ correcte. Vous devez donc apprendre à valider vous même votre code.

  1. Entrez des commentaires

Vous aurez aussi à rentrer du texte pour analyser et commenter votre travail dans des cellules textes markdown. Pour cela vous double cliquez sur la cellule et remplacez le texte suivant

    YOUR ANSWER HERE

par vos commentaires.

ATTENTION on vous demande des commentaires pertinents écrits avec des phrases en français et sans faute d'orthographe. Pour vous aidez, vous avez accès à un correcteur orthographique minimaliste qui colorie les mots éventuellement mal orthographiés.

  1. Soumission du travail

Pour soumettre votre travail exécuter le notebook et suiver les instructions. A la fin appuyer sur submit pour soumettre votre travail

ATTENTION le travail demandé est un travail personnel. Tout étudiant est tenu de respecter les règles relatives au plagiat. Constitue notamment du plagiat le fait de remettre un travail copié en totalité ou en partie d'un autre étudiant (avec ou sans l'accord de cet autre étudiant)

Votre travail sera soumis à un système de détection de plagiat, et vous risquez donc d'être sanctionné en cas de plagiat.

  1. En cas de problème

Tout d'abord, redémarrez le noyau (dans la barre de menus, sélectionnez Noyau -> Redémarer ou Kernel -> Restart), puis exécutez toutes les cellules (dans la barre de menus, sélectionnez Cellule -> Executer tout ou Cellule -> Run All).

  1. Remplir la cellule suivante

Ecrire votre nom, prénom et numéro d'étudiant ci-dessous

In [1]:
NOM    = "BUFFAT"
PRENOM = "Marc"
NUMERO_ETUDIANT = 12345
if type(NUMERO_ETUDIANT) is not int:
    print("ERREUR: numéro d'étudiant non spécifié!!!")

TP analyse de données climatiques

Marc BUFFAT, dpt mécanique, Université Lyon 1

temp_terre.png

[1] librement inspiré par le cours \"Engineering Computations\" du Pr L. Barba (Washington Univ.)

Attention il faut exécuter la cellule vide suivante !!

In [2]:
%matplotlib inline
import numpy as np
import matplotlib.pyplot as plt
from validation.valide_markdown import test_markdown, test_code
from IPython.display import display, Markdown, clear_output
def printmd(string):
    display(Markdown(string))
# test si numero étudiant spécifier
try: NUMERO_ETUDIANT
except NameError: NUMERO_ETUDIANT = None 
if type(NUMERO_ETUDIANT) is not int :
    printmd("## ERREUR: numéro d'étudiant non spécifié!!!")
    NUMERO_ETUDIANT = 123456
    NOM    = "toto"
    PRENOM = "toto"
# parametres spécifiques
_uid_  = NUMERO_ETUDIANT
np.random.seed(_uid_)
printmd("## Etudiant {} {}  id={}".format(NOM,PRENOM,NUMERO_ETUDIANT))
# mots clés
_mcl1_ = ['régression','linéaire','droite','moindres','carrés','anomalie','températures','prédiction', 'prédire',
          'fichier','fonction','moyenne']
# parametres
_i1 = 5   + np.random.randint(10)
_i2 = 146 - np.random.randint(10)
_an = 2030 + np.random.randint(10)
# generation du fichier de donnees
cde="'1,{}d;{},$d'".format(_i1,_i2)
#print("cde:",cde)
!sed $cde ./data/land_global_temperature_anomaly.csv > ./data/anomalie_temperature.csv
printmd("### Objectif du TP: Estimation de la hausse des température en {}".format(_an))

Etudiant BUFFAT Marc id=12345

Objectif du TP: Estimation de la hausse des température en 2031

Objectifs et démarche

le contexte et le principe de l'étude ont été donné dans le notebook de préparation que vous devez avoir lu et compris. Ce notebook de préparation est accessible sur le lien suivant:

Vous devez répondre tout d'abord aux questions suivantes sur les objectifs. dans la cellule de texte suivante, répondre aux questions suivantes en écrivant des phrases en français sans fautes d'orthographe

1. quel est l'objectif du TP
2. quelle est le principe de la méthode 
2. quelles sont les calculs à faire
3. quelles fonctions python dois-je écrire
4. Comment analyser le résultat 

Ecrire les réponses dans la cellule suivante en faisant attention à l'orthographe (sinon vous perdez des points):

L' objectif de l' étude est l'analyse du réchauffement climatique et plus particulièrement l'évolution de l'anomalie climatique depuis un siècle.

Les données sont stockées dans un fichier que l'on va lire pour les mettre dans 2 tableaux pour les analyser. Les données étant bruitées, on va les lisser à l'aide d'une droite: la droite des moindres carrés, qui minimise l'écart entre les mesures et la droite de lissage.

Pour calculer cette régression linéaire, on doit calculer des moyennes de plusieurs tableaux.

Pour se faire, on va écrire une fonction python, qui va calculer la moyenne arithmétique d'un tableau numpy passé en argument.

Ensuite à partir de ce modèle de régression linéaire on va pouvoir faire une prédiction de la hausse des températures dans le futur.

In [5]:
# test 1
assert(test_markdown('TP_donnees_climatiques.ipynb','cell-comment1',minm=20, maxe=0.3)) 
printmd("## Commentaires OK")

Commentaires OK

In [6]:
# test 2
printmd("## Test de pertinence")
assert(test_markdown('TP_donnees_climatiques.ipynb','cell-comment1',minm=30,maxe=0.3,mcl=_mcl1_,maxs=0.7))
printmd("## Pertinence des commentaires OK")

Test de pertinence

Pertinence des commentaires OK

Étape 1: lecture des données

Pour avoir une idée des données, on va utiliser la commande unix/linux head mon_fichier, qui 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.

In [7]:
!head ./data/anomalie_temperature.csv
1882,0.08
1883,-0.28
1884,-0.24
1885,-0.45
1886,-0.18
1887,-0.52
1888,-0.33
1889,-0.03
1890,-0.34
1891,-0.40

lecture du fichier

Pour charger les données à partir du fichier, nous utiliserons la fonction numpy.loadtxt(), qui nous permet de charger 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 a importé la bibliothèque numpy au début pour pouvoir utiliser cette fonction

In [8]:
import numpy as np
annee = 0
anomalie_temp = 0
fichier = './data/anomalie_temperature.csv'
annee, anomalie_temp = np.loadtxt(fichier, delimiter=',', skiprows=5, unpack=True)
print(annee, anomalie_temp)
[1887. 1888. 1889. 1890. 1891. 1892. 1893. 1894. 1895. 1896. 1897. 1898.
 1899. 1900. 1901. 1902. 1903. 1904. 1905. 1906. 1907. 1908. 1909. 1910.
 1911. 1912. 1913. 1914. 1915. 1916. 1917. 1918. 1919. 1920. 1921. 1922.
 1923. 1924. 1925. 1926. 1927. 1928. 1929. 1930. 1931. 1932. 1933. 1934.
 1935. 1936. 1937. 1938. 1939. 1940. 1941. 1942. 1943. 1944. 1945. 1946.
 1947. 1948. 1949. 1950. 1951. 1952. 1953. 1954. 1955. 1956. 1957. 1958.
 1959. 1960. 1961. 1962. 1963. 1964. 1965. 1966. 1967. 1968. 1969. 1970.
 1971. 1972. 1973. 1974. 1975. 1976. 1977. 1978. 1979. 1980. 1981. 1982.
 1983. 1984. 1985. 1986. 1987. 1988. 1989. 1990. 1991. 1992. 1993. 1994.
 1995. 1996. 1997. 1998. 1999. 2000. 2001. 2002. 2003. 2004. 2005. 2006.
 2007. 2008. 2009. 2010. 2011. 2012. 2013. 2014.] [-0.52 -0.33 -0.03 -0.34 -0.4  -0.24 -0.73 -0.42 -0.44 -0.15 -0.13 -0.01
 -0.15 -0.35 -0.14 -0.1  -0.24 -0.62 -0.36 -0.14 -0.37 -0.38 -0.59 -0.36
 -0.55 -0.28 -0.36  0.1  -0.15 -0.13 -0.53 -0.33 -0.24 -0.21 -0.08 -0.31
 -0.24 -0.23 -0.41  0.13 -0.23 -0.08 -0.49 -0.34 -0.03  0.15 -0.29 -0.3
 -0.28 -0.27 -0.18  0.02 -0.11  0.01  0.27  0.3  -0.03  0.39  0.17  0.25
 -0.16  0.07  0.12 -0.29 -0.28  0.13  0.09 -0.2   0.15 -0.14 -0.09  0.32
  0.16  0.04  0.13  0.13  0.06  0.02 -0.07 -0.05 -0.09 -0.2  -0.09  0.14
  0.01 -0.24  0.28 -0.19  0.11 -0.02  0.13  0.17  0.15  0.33  0.51  0.14
  0.53  0.3   0.23  0.32  0.32  0.56  0.17  0.36  0.43  0.46  0.36  0.27
  0.56  0.26  0.34  0.6   0.51  0.34  0.47  0.71  0.72  0.62  0.65  0.51
  0.92  0.27  0.6   0.74  0.47  0.45  0.62  0.7 ]
In [9]:
assert(type(annee) == np.ndarray)
assert(type(anomalie_temp) == np.ndarray)
printmd("### validation OK")

validation OK

Étape 2: tracer des données

Commençons par charger le module pyplot de Matplotlib, pour créer des tracés 2D ainsi que la commande spéciale "magique", % matplotlib inline pour avoir les figures incluses dans le notebook.

Utiliser ensuite la fonction plot() pour tracer l'anomalie de température en fonction de l'année avec

    plt.plot(annee, anomalie_temp)
In [11]:
%matplotlib inline
import matplotlib.pyplot as plt
plt.plot(annee, anomalie_temp)
Out[11]:
[<matplotlib.lines.Line2D at 0x7ff3d6e41358>]

amélioration du tracé

Nous avons maintenant un tracé basique mais sans aucune information,car vous ne pouvez pas déterminer de quel type de données il s'agit! Nous avons besoin d'étiquettes sur les axes, d'un titre et pourquoi pas d'une meilleure couleur, police et taille des graduations.

Un tracé de qualité (au sens d'une publication scientifique) doit toujours être la norme. La façon dont vous présentez vos données permettra aux autres (et probablement à vous à l'avenir) de mieux comprendre votre travail.

Nous pouvons personnaliser le style de nos tracés en utilisant des paramètres pour les lignes, le texte, la police et d'autres options de tracé. Nous définissons des options de style qui s'appliquent à tous les tracés de la session courante avec pyplot.rc() Ici, nous allons créer la police d'un type et d'une taille spécifiques (empattement et 16 points). Vous pouvez également personnaliser d'autres paramètres comme la largeur de ligne, la couleur, etc. (consultez la documentation).

In [12]:
# police des titres
plt.rc('font', family='serif', size='18')
# augmente la taille de la figure
plt.figure(figsize=(10,5))
# tracer
plt.plot(annee, anomalie_temp, color='#2929a3', linestyle='-', linewidth=1) 
plt.title('Anomalie de température\n')
plt.xlabel('Année')
plt.ylabel('anomalie en [°C]')
plt.grid();

Etape 3: régression linéaire par moindres carrés

Afin d'avoir une idée du comportement général de ces 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) qui permet de lisser le bruit toujours présent dans les données expérimentales.

Lissons maintenant 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$

$$ y = a_1 x + a_0 $$

avec pour expression des coefficients $a_1$ et $a_0$:

\begin{eqnarray} a_1 = \frac{\sum_{i = 0}^{n} y_ {i} (x_i - \bar{x})} {\sum_{i = 0}^{n} x_i (x_i - \bar{x })} \quad, \quad a_0 = \bar {y} - a_1 \bar {x} \end{eqnarray}

Dans notre cas, les données x sont dans le tableau annee, et les données y sont dans le tableau anomalie_temp. 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.

question 1: définition

Définir une fonction valeur_moyenne qui calcule la valeur moyenne de n'importe quel tableau passé en argument. On devra utiliser une boucle for sur les valeurs du tableau et ne pas utiliser la méthode .mean() de numpy qui calcule la moyenne arithmétique d'un tableau.

On testera la fonction dans la cellule suivante avant de passer le test de validation

In [13]:
def valeur_moyenne(tableau):
    """ Calcul la valeur moyenne d'un tableau
    
    Argument
    ---------
    tableau: Numpy array 
    
    Retour
    -------    
    moyenne des valeurs du tableau
    """
    moyenne = 0
    for val in tableau:
        moyenne = moyenne + val
    return moyenne / len(tableau)
In [15]:
# tester votre fonction ici pour calculer la moyenne des entiers de 1 à 10 et de 0 à 10
valeur_moyenne(np.arange(1,11)), valeur_moyenne(np.arange(0,11))
Out[15]:
(5.5, 5.0)
In [16]:
_X = np.linspace(0,1000000000,1000)
assert (np.abs(_X.mean()-valeur_moyenne(_X))> 1.e-9)
printmd("la fonction valeur_moyenne n'utilise pas mean")
assert (np.abs(valeur_moyenne(np.linspace(1,3,11)) - 2.) < 1.e-10)
printmd("Validation OK")

la fonction valeur_moyenne n'utilise pas mean

Validation OK

question 2: utilisation

Une fois que vous avez définie la fonction valeur_moyenne(), elle devient disponible pour être utilisée avec n'importe quel tableau de n'importe quelle dimension. Essayons la avec nos données pour calculer la valeur moyenne des tableaux annee et anomalie_temp et mettre le résultat dans 2 variables moyenne_annee et moyenne_anomalie.

In [ ]:
moyenne_annee = 0
moyenne_anomalie = 0
# YOUR CODE HERE
raise NotImplementedError()
In [ ]:
print("moyenne annee=",moyenne_annee)
assert (np.abs(moyenne_annee - annee.mean()) < 1.e-10)
print("moyenne anomalie temp.=",moyenne_anomalie)
assert (np.abs(moyenne_anomalie - anomalie_temp.mean()) < 1.e-10)
printmd("### Validation OK")

question 3: calcul des coefficients

Maintenant que nous avons des valeurs moyennes, nous pouvons calculer nos coefficients en suivant les équations précédentes. Nous calculons d'abord $ a_1 $ puis utilisons cette valeur pour calculer $ a_0 $.

Nos coefficients sont donnés par les relations: $$ a_1 = \frac{ \sum_{i=0}^{n} y_{i} (x_i - \bar{x})}{\sum_{i=0}^{n} x_i (x_i - \bar{x})} \quad , \quad a_0 = \bar{y} - a_1\bar{x} $$

Nous avons déjà calculé les valeurs moyennes des tableaux de données, mais la formule nécessite deux sommes sur les nouveaux tableaux dérivés. Récrire la formule précédente pour faire apparaître uniquement les moyenne des x, des y et des moyennes de nouveaux tableaux calculés en fonction de x et y.

Créer 2 tableaux dérivées XY et X2 pour calculer a1 en utilisant cette nouvelle expression pour les tableaux X = annee et Y = anomalie_temp.

En déduire la valeur de $a_1$ et $a_0$.

In [ ]:
X = annee
Y = anomalie_temp
X2 = 0
XY = 0
a0 = 0
a1 = 0
# YOUR CODE HERE
raise NotImplementedError()
In [ ]:
assert (np.abs(a1 - np.sum(X*(Y-np.ndarray.mean(Y)))/np.sum(X*(X-np.ndarray.mean(X)))) < 1.e-10)
printmd("Validation OK")

question 4: lissage

Écrivez une fonction qui calcule les coefficients $a_0$ et $a_1$, appelez la fonction pour les calculer et comparez le résultat avec les valeurs que nous avons obtenues auparavant. À titre indicatif, nous vous donnons la structure que vous devez suivre:

def coefficients_lissage(x, y):
    """
    ecrire la description docstrings
    """

    a1 = xxx
    a0 = yyy

    return a1, a0

pour les données du problème, l'appel de cette fonction

      coefficients_lissage(annee,anomalie_temp)

renvoie la valeur calculéee de $a_0$ et $a_1$

In [ ]:
def coefficients_lissage(x, y):
    """
    calcul les coefficients de la droite de moindres carrés lissant les points x,y
    renvoie les valeurs a1,a0  (droite a1*x+a0)
    """

    a1 = 0
    a0 = 0
    # YOUR CODE HERE
    raise NotImplementedError()
    return a1, a0
In [ ]:
# tester par rapport au calcul précédent de a1 et a0
# YOUR CODE HERE
raise NotImplementedError()
In [ ]:
"""test si coefficients_lissage depends de valeur_moyenne."""
from nose.tools import assert_raises
orig_valeur_moyenne = valeur_moyenne
del valeur_moyenne
try:
    assert_raises(NameError, coefficients_lissage, annee, anomalie_temp)
except AssertionError:
    raise AssertionError("coefficients_lissage ne depends pas de valeur_moyenne")
finally:
    valeur_moyenne = orig_valeur_moyenne
printmd("### Validation OK")

Nous avons maintenant les coefficients d'une fonction linéaire qui lisse les données. Nous pouvons maintenant calculer les valeurs prédites d'anomalie de température $ f (x) $ avec $$ f(x) = a_0 + a_1 x$$

Appelons reg le tableau obtenu en évaluant $ f (x) $ pour toutes les valeurs du tableau annee:

    reg = a0 + a1*annee

Calculer les valeurs de $a_0$ et $a_1$, puis les valeurs du tableau reg

In [ ]:
a0 = 0
a1 = 0
reg = 0
# YOUR CODE HERE
raise NotImplementedError()
In [ ]:
assert(len(reg) == len(annee))
printmd("### Validation OK")

Avec les valeurs de notre régression linéaire, nous pouvons la tracer avec des données d'origine pour voir à quoi elles ressemblent. Etudiez le code ci-dessous.

In [ ]:
plt.figure(figsize=(10, 8))

plt.plot(annee, anomalie_temp, color='#2929a3', linestyle='-', linewidth=1, alpha=0.5) 
plt.plot(annee, reg, 'k--', linewidth=2, label='Regression linéaire')
plt.xlabel('Annee')
plt.ylabel('Anomalie de temperature [°C]')
plt.legend(loc='best', fontsize=15)
plt.grid();

question 5: prédiction

On va utiliser les données précédentes pour obtenir une prédiction de la hausse des températures (si la tendance actuelle se confirme) dans l'année donnée ci dessous.

Dans la cellule suivante, calculer la valeur de cette prédiction dans la variable prediction et faite une petite analyse du résultat. On utilisera la fonction numpy np.round(val,2) qui arrondit une valeur val à 2 chiffres après la virgule (on expliquera pourquoi).

In [ ]:
printmd("### Estimation de la hausse des température en {}".format(_an))
In [ ]:
prediction = 0
# YOUR CODE HERE
raise NotImplementedError()
In [ ]:
print("prédiction de la hausse de temperature: {} degré en {}".format(prediction,_an))
assert (prediction*100 - np.trunc(prediction*100) == 0.)
printmd("### Validation OK")

Question 6: analyse

Ecrire vos commentaires et votre analyse du résultat obtenu ci-dessous. On essayera de répondre aux question suivantes, en justifiant:

1. Le résultat obtenu est-il plausible, sur-évalué ou sous-évalué ?
2. Que peut dire de la courbe d'évolution de l'anomalie de température, en particulier à partir des années 1970 ?
3. La prédiction permet-elle de suivre cette tendance des dernières années ?

</span>

YOUR ANSWER HERE

In [ ]:
# test 2
assert(test_markdown('TP_donnees_climatiques.ipynb','cell-comment2',minm=20, maxe=0.3)) 
printmd("## Commentaires OK")

Conclusion

Ecrire votre conclusion en utilisation la cellule de texte suivante au format markdown, en utilisant le plan suivant

  1. Synthèse de la démarche et du résultat obtenu
  2. Piste d'amélioration
  3. Conclusion

En particulier comparez vos résultats avec plusieurs de vos camarades. Que pouvez vous en conclure.

YOUR ANSWER HERE

In [ ]:
# test 2
assert(test_markdown('TP_donnees_climatiques.ipynb','cell-comment2',minm=20, maxe=0.3)) 
printmd("## Commentaires OK")

FIN du TP

In [ ]:
# version
from platform import python_version,uname,platform
print("Systeme       :",uname())
print("OS            :",platform())
print("version python:",python_version())
print("version numpy :",np.__version__)
In [ ]: