Chapitre 2 : Python

Le python est une famille de reptile avec pas de pattes comprenant 10 espèces. Mais Python est un langage de programmation lancé en 1991 par Guido van Rossum, un fan du groupe d'humoriste britanique Mounty Python.

Source: Ministry of silly walks, Mounty Python

Python figure parmi les langages de programmation les plus utilisés au monde. Il s'agit d'un langage dynamique, c'est à dire que le code peut être exécuté ligne par ligne ou bloc par bloc: un avantage majeur pour des activités qui nécessitent des intéractions fréquentes. Bien que Python soit surtout utilisé pour créer des applications, il s'impose de plus en plus comme outil privilégié pour le calcul scientifique en raison des récents développements de bibliothèques d'analyse, de modélisation et de visualisation, dont plusieurs seront utilisés dans ce manuel.

Préparer son ordinateur

Installer Python

Installer et gérer Python sur un ordinateur serait une tâche plutôt ardue si ce n'était de la distribution Anaconda, spécialisée pour le calcul scientifique. Anaconda est distribué librement sur Linux, Windows et OS X (il existe d'autres distribution Python équivalentes, notamment Enthought et Python(x,y)). Il est possible de travailler sur Python en mode infonuagique, notamment avec SageMath. Toutefois, l'option nuagique n'est en ce moment pas à la hauteur d'un environnement local en terme d'efficacité, de polyvalence et d'autonomie.

Sur Windows et sur OS X, téléchargez et installez! Sur Linux, téléchargez, ouvrez un terminal, naviguez dans le répertoire de téléchargement (par exemple cd ~/Téléchargements), puis lancez la commande spécifiée sur la page de téléchargement, par exemple bash Anaconda3-4.3.1-Linux-x86_64.sh.

Note. Les modules présentés dans ce cours devraient être disponibles sur Linux, Windows et Mac. Ce n'est pas le cas pour tous les modules Python. La plupart fonctionnent néanmoins sur Linux. Que ce soit sur Ubuntu, l'une de ses nombreuses dérivées (Elementary, Linux Mint, KDE Neon, etc.), sous Debian, openSUSE, Arch, Fedora ou autre, les systèmes d'opération Linux sont de bonnes options pour le calcul scientifique.

Premiers pas avec Python

Voyons si Python est aussi libre qu'on le prétend. Si Python est bien installé sur votre ordinateur, la manière la plus directe de le lancer est en ouvrant un terminal (chercher cmd dans le menu si vous êtes sur Windows). Dans ce terminal, écrivez python, puis tapez enter. Vous devriez obtenir quelque chose comme ceci.

Les symboles >>> forment ce que l'on nomme l'invite de commande. J'entre ici les commandes dans le carnet, mais pour l'instant, entrez-les dans le terminal (on débutera avec les carnets un peu plus loin).

Opérations de base

"La liberté, c’est la liberté de dire que deux et deux font quatre. Si cela est accordé, tout le reste suit." - George Orwell, 1984


In [7]:
2+2


Out[7]:
4

In [8]:
67.1-43.3


Out[8]:
23.799999999999997

In [9]:
2*4


Out[9]:
8

In [10]:
2**4


Out[10]:
16

In [11]:
1/2


Out[11]:
0.5

In [12]:
1 / 2 # les espaces ne signifie rien ici


Out[12]:
0.5

Tout va bien pour l'instant. Remarquez que la dernière opération comporte des espaces entre les nombres et l'opérateur /. Dans ce cas (ce n'est pas toujours le cas), les espaces ne signifient rien - il est même suggéré de les placer pour éclaircir le code, ce qui est utile lorsque les équations sont complexes. Puis, après l'opération 1 / 2, j'ai placé le symbole # suivi d'une note. Le symbole # est interprété par Python comme un ordre de ne pas considérer ce qui le suit. Cela est très utile pour insérer à même le code des commentaires pertinents pour mieux comprendre les opérations.

Assigner des objets à des variables est fondamental en programmation. Par exemple.


In [5]:
a = 3

Techniquement, a pointe vers le nombre entier 3. Conséquemment, on peut effectuer des opérations sur a.


In [6]:
a * 6


Out[6]:
18

In [7]:
A + 2


---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
<ipython-input-7-df3d83145d14> in <module>()
----> 1 A + 2

NameError: name 'A' is not defined

Le message d'erreur nous dit que A n'est pas défini. Sa version minuscule, a, l'est pourtant. La raison est que Python considère la case dans la définition des objets. Utiliser la mauvaise case mène donc à des erreurs.

Le nom d'une variable doit toujours commencer par une lettre, et ne doit pas contenir de caractères réservés (espaces, +, *, .). Par convention, les objets qui commencent par une lettre majuscules sont utilisés pour définir des classes (modules), utiles pour le développement de logiciels, mais rarement utilisés dans le cadre d'un feuille de calcul scientifique.


In [8]:
rendement_arbre = 50 # pomme/arbre
nombre_arbre = 300 # arbre
nombre_pomme = rendement_arbre * nombre_arbre
nombre_pomme


Out[8]:
15000

Types de données

Jusqu'à maintenant, nous n'avons utilisé que des nombres entiers (integer ou int) et des nombres réels (float ou float64). Python inclue d'autres types. La chaîne de caractère (string) est un ou plusieurs symboles. Elle est définie entre des double-guillemets " " ou des apostrophes ' '. Il n'existe pas de standard sur l'utilisation de l'un ou de l'autre, mais en règle générale, on utilise les apostrophe pour les experssions courtes, contenant un simple mot ou séquence de lettres, et les guillements pour les phrases. Une raison pour cela: les guillemets sont utiles pour insérer des apostrophes dans une chaîne de caractère.


In [9]:
a = "L'ours"
b = "polaire"
a + " " +  b + " ressemble à un faux zèbre."


Out[9]:
"L'ours polaire ressemble à un faux zèbre."

Notez que l'objet a a été défini précédemment. Il est possible en Python de réassigner une variable, mais cela peut porter à confusion, jusqu'à générer des erreurs de calcul si une variable n'est pas assigné à l'objet auquel on voulait référer.

L'opérateur + sur des caractères retourne une concaténation.

Combien de caractères contient la chaîne "L'ours polaire"? Python sait compter. Demandons-lui.


In [10]:
c = a + " " +  b
len(c)


Out[10]:
14

Quatorze, c'est bien cela (comptez "L'ours polaire", en incluant l'espace). len, pour lenght (longueur), est une fonction (aussi appelée méthode) incluse par défaut dans l'environnement de travail de Python. La fonction est appelée en écrivant len(). Mais une fonction de quoi? Des arguments qui se trouvent entre les parenthèses. Dans ce cas, il y a un seul argument: c.

En calcul scientifique, il est courrant de lancer des requêtes sur si une résultat est vrai ou faux.


In [11]:
a = 17
print(a < 10)
print(a > 10)
print(a == 10)
print(a != 10)
print(a == 17)
print(~a == 17)


False
True
False
True
True
False

Je viens d'introduire un nouveau type de donnée: les données booléennes (boolean, ou bool), qui ne peuvent prendre que deux états - True ou False. En même temps, j'ai utilisé la fonction print parce que dans mon carnet, seule la dernière opération permet d'afficher le résultat. Si l'on veut forcer une sortie, on utilise print. Puis, on a vu plus haut que le symbole = est réservé pour assigner des objets: pour les tests d'égalité, on utilise le double égal, ==, ou != pour la non égalité. Enfin, pour inverser une donnée de type booléenne, on utilise le symbole ~.

Pour les tests sur les chaînes de caractères, on utilisera in et son inverse not in.


In [14]:
print('o' in 'Ours')
print('O' in 'Ours')
print('O' not in 'Ours')


False
True
False

Les collections de données

Les exercices précédents ont permis de présenter les types de données offerts par défault sur Python qui sont les plus importants pour le calcul scientifique: int (integer, ou nombre entier), float64 (nombre réel), str (string, ou chaîne de caractère) et bool (booléen). D'autres s'ajouterons tout au long du cours, comme les unités de temps (date-heure), les catégories et les géométries (points, linges, polygones) géoréférencées. Lorsque l'on procède à des opérations de calcul en science, nous utilisons rarement des valeurs uniques. Nous préférons les oragniser et les traiter en collections. Par défaut, Python offre trois types importants: les listes, les tuples et les dictionnaires.

D'abord, les listes, ou list, sont une série de variables sans restriction sur leur type. Elles peuvent même contenir d'autres listes. Une liste est délimitée par des crochets [ ], et les éléments de la liste sont séparés par des virgules.


In [15]:
espece = ['Petromyzon marinus', 'Lepisosteus osseus', 'Amia calva', 'Hiodon tergisus']
espece


Out[15]:
['Petromyzon marinus', 'Lepisosteus osseus', 'Amia calva', 'Hiodon tergisus']

Pour accéder aux éléments d'une liste, appelle la liste suivie de la position de l'objet désiré entre crochets. Fait important qui reviendra tout au long du cours: en Python, l'indice du premier élément est zéro.


In [16]:
print(espece[0])
print(espece[2])
print(espece[:2])
print(espece[2:])


Petromyzon marinus
Amia calva
['Petromyzon marinus', 'Lepisosteus osseus']
['Amia calva', 'Hiodon tergisus']

Pour les deux dernières commandes, la position :2 signifie jusqu'à 2 non inclusivement et 2: signifie de 2 à la fin.

Pour ajouter un élément à notre liste, on peut utiliser la fonction append.


In [17]:
espece.append("Cyprinus carpio")
espece


Out[17]:
['Petromyzon marinus',
 'Lepisosteus osseus',
 'Amia calva',
 'Hiodon tergisus',
 'Cyprinus carpio']

Notez que la fonction append est appelée après la variable et précédée un point. Cette manière de procéder est courrante en programmation orientée objet. La fonction append est un attribut d'un objet list et prend un seul argument: l'objet qui est ajouté à la liste. C'est une manière de dire grenouille.saute(longueur=1.0).

En lançant espece[2] = "Lepomis gibbosus", on note qu'il est possible de changer une élément de la liste.


In [19]:
print(espece)
espece[2] = "Lepomis gibbosus"
print(espece)


['Petromyzon marinus', 'Lepisosteus osseus', 'Amia calva', 'Hiodon tergisus', 'Cyprinus carpio']
['Petromyzon marinus', 'Lepisosteus osseus', 'Lepomis gibbosus', 'Hiodon tergisus', 'Cyprinus carpio']

Si les données contenues dans une liste sont de même type, cette liste peut être considérée comme un vecteur. En créant une liste de vecteurs de dimensions cohérentes, on crée une matrice. Nous verrons plus tard que pour les vecteurs et les matrices, on utilisera un format offert par un module complémentaire. Pour l'instant, on pourrait définir une matrice comme suit.


In [16]:
mat = [[1, 2, 3],
       [4, 5, 6],
       [7, 8, 9],
       [10, 11, 12]]
mat


Out[16]:
[[1, 2, 3], [4, 5, 6], [7, 8, 9], [10, 11, 12]]

Les tuples, définis tuple par Python, différent des listes du fait que ses éléments ne peuvent pas être modifiés. Un tuple est délimité par des parenthèses ( ), et comme chez la liste, ses éléments sont séparés par des virgules. Les tuples sont moins polyvalents que les listes. Vous les utiliserez probablement rarement, et surtout comme arguments dans certaines fonctions en calcul scientifique.


In [17]:
espece = ('Petromyzon marinus', 'Lepisosteus osseus', 'Amia calva', 'Hiodon tergisus')
espece[2] = "Lepomis gibbosus"
espece


---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-17-015dcfee479d> in <module>()
      1 espece = ('Petromyzon marinus', 'Lepisosteus osseus', 'Amia calva', 'Hiodon tergisus')
----> 2 espece[2] = "Lepomis gibbosus"
      3 espece

TypeError: 'tuple' object does not support item assignment

Les dictionnaires, ou dict, sont des listes dont chaque élément est identifié par une clé. Un dictionnaire est délimité par des accolades sous forme mon_dict = {'clé1': x, 'clé2': y, 'clé3': z }. On appelle un élément par sa clé entre des crochets, par exemple mon_dict['clé1'].

Le dict se rapproche d'un tableau: nous verrons plus tard que le format de tableau (offert dans un module complémentaire) est bâti à partir du format dict. Contrairement à un tableau où les colonnes contiennent toutes le même nombre de lignes, chaque élément du dictionnaire est indépendant des autres.


In [21]:
tableau = {'espece': ['Petromyzon marinus', 'Lepisosteus osseus', 'Amia calva', 'Hiodon tergisus'], 'poids': [10, 13, 21, 4], 'longueur': [35, 44, 50, 8]}
print('Mon tableau: ', tableau)
print('Mes espèces:',  tableau['espece'])
print('Noms des clés (ou colonnes):',  tableau.keys())


Mon tableau:  {'poids': [10, 13, 21, 4], 'espece': ['Petromyzon marinus', 'Lepisosteus osseus', 'Amia calva', 'Hiodon tergisus'], 'longueur': [35, 44, 50, 8]}
Mes espèces: ['Petromyzon marinus', 'Lepisosteus osseus', 'Amia calva', 'Hiodon tergisus']
Noms des clés (ou colonnes): dict_keys(['poids', 'espece', 'longueur'])

Les fonctions (ou méthodes)

Plus haut, j'ai présenté les fonctions len et append. Une myriade de fonctions sont livrées par défaut avec Python. Mais il en manque aussi cruellement.


In [18]:
sqrt(2)


---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
<ipython-input-18-40e415486bd6> in <module>()
----> 1 sqrt(2)

NameError: name 'sqrt' is not defined

Message d'erreur: la commande sqrt n'est pas définie.

Quoi, Python n'est pas foutu de calculer une racine carrée?

Par défaut, non.

Mais!

De nombreuses extensions (les modules) permettent de combler ces manques. Nous aborderons ça un peu plus loin dans ce chapitre. Pour l'instant, exerçons-nous à créer notre propre fonction de racine carrée.


In [20]:
def racine(x, n=2):
    r = x**(1/n)
    return r

En Python, def est le mot-clé pour définir une fonction. Suit ensuite, après un espace, le nom que vous désirez donner à la fonction: racine. Les arguments de la fonction suivent entre les parenthèses. Dans ce cas, x est la valeur de laquelle on veut extraire la racine et n est l'ordre de la racine. L'agument x n'a pas de valeur par défaut: elle doit être spécifiée pour que la fonction fonctionne. La mention n=2 signifie que si la valeur de n n'est pas spécifiée, elle prendra la valeur de 2 (la racine carrée). Pour marquer la fin de la définition et le début de la suite d'instructions, on utilise les deux points :, puis un retour de ligne. Une indentation (ou retrait) de quatre barres d'espacement signifie que l'on se trouve à l'intérieur de la suite d'instructions, où l'on calcule une valeur de r comme l'exposant de l'inverse de l'ordre de la racine. La dernière ligne indique ce que la fonction doit retourner.


In [21]:
print(racine(9))
print(racine(x=9))
print(racine(8, 3))
print(racine(x=8, n=3))


3.0
3.0
2.0
2.0

S'ils ne sont pas spécifiés, Python comprend que les arguments sont entrés dans l'ordre défini dans la fonction. En entrant racine(9), Python comprend que le 9 est attribué à x et donne à n sa valeur par défaut, 2. Ce qui est équivalent à entrer racine(x=9). Les autres entrées sont aussi équivalentes, et extraient la racine cubique. S'il se peut qu'il y ait confusion entre les arguments nommés et ceux qui ne le sont pas, Python vous retournera un message d'erreur. Règle générale, il est préférable pour la lisibilité du code de nommer les arguments plutôt que de les spécifier dans l'ordre.

Supposons maintenant que vous avez une liste de données dont vous voulez extraire la racine.


In [22]:
data = [3.5, 8.1, 10.2, 0.5, 5.6]
racine(x=data, n=2)


---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-22-2392ba347f65> in <module>()
      1 data = [3.5, 8.1, 10.2, 0.5, 5.6]
----> 2 racine(x=data, n=2)

<ipython-input-20-5b6054ea860f> in racine(x, n)
      1 def racine(x, n=2):
----> 2     r = x**(1/n)
      3     return r

TypeError: unsupported operand type(s) for ** or pow(): 'list' and 'float'

Oups. Python vous dit qu'il y a une erreur, et vous indique avec une flèche ----> à quelle ligne de notre fonction elle est encourrue. Les exposants ** (on peut aussi utiliser la fonction pow) ne sont pas applicables aux listes. Une solution est d'appliquer la fonction à chaque élément de la liste avec une ittération. On verra plus tard des manières plus efficaces de procéder. Je me sers de ce cas d'étude pour introduire les boucles ittératives.

Les boucles

Les boucles permettent d'effectuer une même suite d'opérations sur plusieurs objets. Pour faire suite à notre exemple:


In [26]:
racine_data = []
for i in [0, 1, 2, 3, 4]:
    r = racine(x=data[i], n=2)
    racine_data.append(r)

racine_data


Out[26]:
[1.8708286933869707,
 2.8460498941515415,
 3.1937438845342623,
 0.7071067811865476,
 2.3664319132398464]

Nous avons d'abord créé une liste vide, racine_data. Ensuite, pour (for) chaque indice de la liste (i in [0, 1, 2, 3, 4]), nous demandons à Python d'effectuer la suite d'opération qui suit le ; et qui est indentée de quatre espaces. Dans la suite d'opération, calculer la racine carrée de data à l'indice i, puis l'ajouter à la liste racine_data. Au lieu d'entrer une liste [0, 1, 2, 3, 4], on aurait pu utiliser la fonction range et lui assigner automatiquement la longueur de la liste.


In [27]:
racine_data = []
for i in range(len(data)):
    r = racine(x=data[i], n=2)
    print('Racine carrée de ', data[i], ' = ', r)
    racine_data.append(r)


Racine carrée de  3.5  =  1.8708286933869707
Racine carrée de  8.1  =  2.8460498941515415
Racine carrée de  10.2  =  3.1937438845342623
Racine carrée de  0.5  =  0.7071067811865476
Racine carrée de  5.6  =  2.3664319132398464

La fonction range retourne une séquence calculée au besoin. Elle est calculée si elle est évoquée dans une boucle ou en lançant list.


In [28]:
print(range(len(data)))
print(list(range(len(data))))
print(range(2, len(data)))
print(list(range(2, len(data))))


range(0, 5)
[0, 1, 2, 3, 4]
range(2, 5)
[2, 3, 4]

Première observation, si un seul argument est inclus, range retourne une séquence partant de zéro. Seconde observation, la séquence se termine en excluant l'argument. Ainsi, range(2,5) retourne la séquence [2, 3, 4]. En spécifiant la longueur de data comme argument, la séquence range(5) retourne la liste [0, 1, 2, 3, 4], soit les indices dont nous avons besoin pour itérer dans la liste.

Les boucles for vous permettront par exemple de générer en peu de temps 10, 100, 1000 graphiques (autant que vous voulez), chacun issu de simulations obtenues à partir de conidtions initiales différentes, et de les enregistrer dans un répertoire sur votre ordinateur. Un travail qui pourrait prendre des semaines sur Excel peut être effectué en Python en quelques secondes.

Un second outil est disponible pour les itérations: les boucles while. Elles effectue une opération tant qu'un critère n'est pas atteint. Elles sont utiles pour les opérations où l'on cherche une convergence. Je les couvre rapidement puisque'elles sont rarement utilisées dans les flux de travail courrants. En voici un petit exemple.


In [29]:
x = 100
while (x > 1.1):
    x=racine(x)
    print(x)


10.0
3.1622776601683795
1.7782794100389228
1.333521432163324
1.1547819846894583
1.0746078283213176

Nous avons inité x à une valeur de 100. Puis, tant que (while) le test x > 1.1 est vrai, attribuer à x la nouvelle valeur calculée en extrayant la racine de la valeur précédente de x. Enfin, indiquer la valeur avec print.

Explorons maintenant comment Python réagit si on lui demande de calculer $\sqrt{-1}$.


In [30]:
racine(x=-1, n=2)


Out[30]:
(6.123233995736766e-17+1j)

D'abord, Python ne retourne pas de message d'erreur, mais un nouveau type de donnée: le nombre imaginaire. Puis, 6.123233995736766e-17 n'est pas zéro, mais très proche. La résolution des calculs étant numérique, on obeserve parfois de légères déviations par rapport aux solutions mathématiques.

Si pour un cas particulier, on veut éviter que notre fonction retourne un nombre imaginaire, comment s'y prendre? Avec une condition.

Conditions: if, elif, else

Si la condition 1 est remplie, effectuer une suite d'instruction 1. Si la condition 1 n'est pas remplie, et si la condition 2 est remplie, effectuer la suite d'instruction 2. Sinon, effectuer la suite d'instruction 3.

Voilà comment on exprime une suite de conditions. Pour notre racine d'un nombre négatif, on pourrait procéder comme suit.


In [31]:
def racine_positive_nn(x, n=2):
    if x<0:
        raise ValueError("x est négatif")
    elif x==0:
        raise ValueError("x est nul")
    else:
        r = x**(1/n)
        return r

La racine positive et non-nulle (racine_positive_nn) comprend les mot-clés if (si), elif (une contration de else if) et else (sinon). ValueError est une fonction pour retourner un message d'erreur lorsqu'elle est précédée de raise. Comme c'est le cas pour def et for, les instructions des conditions sont indentées. Notez la double indentation (8 espaces) pour les instructions des conditions. Alors que la plupart des langages de programmation demandent d'emboîter les instructions dans des parenthèses, accolades et crochets, Python préfère nous forcer à bien indenter le code (ce que l'on devrait faire de toute manière pour améliorer la lisibilité) et s'y fier pour effectuer ses opérations.


In [32]:
racine_positive_nn(x=-1, n=2)


---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-32-433df026cdcb> in <module>()
----> 1 racine_positive_nn(x=-1, n=2)

<ipython-input-31-50ae7c2c1de7> in racine_positive_nn(x, n)
      1 def racine_positive_nn(x, n=2):
      2     if x<0:
----> 3         raise ValueError("x est négatif")
      4     elif x==0:
      5         raise ValueError("x est nul")

ValueError: x est négatif

In [33]:
racine_positive_nn(x=0, n=2)


---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-33-f8ae6dbb9aea> in <module>()
----> 1 racine_positive_nn(x=0, n=2)

<ipython-input-31-50ae7c2c1de7> in racine_positive_nn(x, n)
      3         raise ValueError("x est négatif")
      4     elif x==0:
----> 5         raise ValueError("x est nul")
      6     else:
      7         r = x**(1/n)

ValueError: x est nul

In [34]:
racine_positive_nn(x=4, n=2)


Out[34]:
2.0

Charger un module

Le module numpy, installé par défaut avec Anaconda, est une boîte d'outil de calcul numérique populée par de nombreuses foncions mathématiques. Dont la racine carrée.


In [1]:
import numpy as np
np.sqrt(9)


Out[1]:
3.0

In [36]:
from numpy import sqrt
sqrt(9)


Out[36]:
3.0

La plupart des fonctions que vous aurez à construire seront vouées à des instructions spécialisées à votre cas d'étude. Pour la plupart des opérations d'ordre générale (comme les racines carrées, les tests statistiques, la gestion de matrices et de tableau, les graphiques, les modèles d'apprentissage, etc.), des équipes ont déjà développé des fonctions nécessaires à leur utilisation, et les ont laissées disponibles au grand public. L'introduction à Python se termine là-dessus.

Comme une langue, on n'apprend à s'exprimer en un langage informatique qu'en se mettant à l'épreuve, ce que vous ferez tout au long de ce cours.

Prenons une pause de Python et passons à des technicalités.

L'environnement de travail

Le gestionnaire conda

Une fois que Anaconda est installé, l'installation de modules et des environnements virtuel devient possible avec le gestionnaire conda. Cette section ne présente qu'un aperçu de ses capacités, basé sur ce dont vous aurez besoin pour ce cours. Pour plus d'information, consultez le guide.

Installer des modules

Sans module, Python ne sera pas un environnement de calcul scientifique appréciable. Heureusement, il existe des modules pour faciliter la vie des scientifiques qui désirent calculer des opérations simples comme des moyennes et des angles, ou des opérations plus compliquées comme des intégrales et des algorithmes d'intelligence artificielle. Plusieurs modules sont installés par défaut avec Anaconda. Pour lister l'ensemble des modules installés dans un environnement, ouvrez un terminal (si vous vous trouvez dans une session Python, vous devez quitter par la commande quit()) et lancez:

conda list

Les modules sont téléchargés et installés depuis des dépôts en ligne. L'entreprise Continuum Analytics, qui développe et supporte Anaconda, offre ses propres dépôts. Par défaut, le module statsmodels (que nous utiliserons pour certaines opérations) sera téléchargé depuis les dépôts par défaut si vous lancez:

conda install statsmodels

Il est préférable d'utiliser le dépôt communautaire conda-forge plutôt que les dépôts officiels de Continuum Analytics. Sur conda-forge, davantage de modules sont disponibles, ceux-ci sont davantage à jour et leur qualité est contrôlée.

conda config --add channels conda-forge

Par la suite, tous les modules seront téléchargés depuis conda-forge. Pour effectuer une mise à jour de tous les modules, lancez:

conda update --all

Installer des environnements virtuels

Vous voilà en train de travailler sur des données complexes qui demandent plusieurs opérations. Vous avez l'habitude, à toutes les semaines, de lancer conda update --all pour mettre à jour les modules, ce qui corrige les bogues et ajoute des fonctionnalités. L'équipe de développement d'un module a décidé de modifier, pour le mieux, une fonction. Vous n'êtes pas au courant de ce changement et vous passez deux jours à cherche ce qui cause ce message d'erreur dans vos calculs. Vous envoyez votre fichier de calcul à votre collègue qui n'a pas mis à jour ce module, puis vos corrections lui causent des problèmes. Croyez-moi, ça arrive souvent.

Les environnements virtuels sont là pour éviter cela. Il s'agit d'un répertoire dans lequel Python ainsi que ses modules sont isolés. Pour un projet spécifique, vous pouvez créer un environnement virtuel sous Python 2.7.9 et installer des versions de modules spécifiques sans les mettre à jour. Ça permet d'une part de travailler avec des outils qui ne changent pas en cours de projet, et d'autre part à travailler entre collègues avec les mêmes versions.

Pour créer un environnement nommé fertilisation_laitue incluant Python en version 2.7.9 et le module statsmodels version 0.6.0, lancez:

conda create -n fertilisation_laitue python=2.7.9

Le répertoire de projet sera automatiquement installé dans le répertoire envs de votre installation de Anaconda.

Pour activer cet environnement, sous Linux et en OS X:

source activate fertilisation_laitue

Sous Windows:

activate fertilisation_laitue

Depuis l'environnement virtuel, vous pouvez installer les modules dont vous avez besoin, en spécifiant la version. Par exemple,

conda install statsmodels=0.6.0

Depuis votre environnement virtuel (y compris l'environnement root), vous pouvez aussi lancer Jupyter, une interface qui vous permettra d'intéragir de manière conviviale avec Python.

À titre d'exemple, préparons-nous au cours en créant un environnement virtuel qui incluera la version de Python 3.5. Précédemment, nous avions fait cela en deux étapes: (1) créer l'environnement, puis (2) installer les bibliothèques. Nous pouvons tout aussi bien le faire d'un coup. Je nomme arbitrairement l'environnement ecolopy.

conda create -n ecolopy numpy scipy pandas matplotlib jupyterlab

Activons l'environnement (Linux et OS X: source activate ecolopy, Windows: activate ecolopy), puis installons les bibliothèques nécessaires. Puisque j'utilise Linux,

source activate ecolopy

Pour partager un environnement de travail avec des collègues ou avec la postérité, vous pouvez générer une liste de prérequis via conda list -e > req.txt, à partir de laquelle quiconque utlise Anaconda pourra créer un environnement virtuel identique au vôtre via conda create -n ecolopy environment --file req.txt.

Pour tester l'environnement, lancez python!

python

Pour ce cours, vous êtes libres de générer un environnement de travail ou de travailler dans l'environnement par défaut (nommé root).

La première ligne importe le module NumPy (numpy) et en crée une instance dont on choisi optionnellement le nom: np (utilisé conventionnellement pour numpy). Ce faisant, on appelle numpy et on le lie avec np. Ainsi, on peut aller chercher l'instance sqrt de np avec np.sqrt(). Si l'on ne cherche qu'à importer la fonction sqrt et que l'on ne comte pas utiliser le tout NumPy:

De nombreux modules seront utilisés lors de ce cours. La section suivante vise à les présenter brièvement.

Modules de base

NumPy

NumPy, une contraction de Numerical Python, donne accès à de nombreuses fonctions mathématiques et intervient inmanquablement pour effectuer des opérations sur les matrices. La grande majorité des opérations effectuées lors de ce cours fera explicitement ou implicitement (via un autre module s'appuyant sur NumPy) référence à NumPy. NumPy permet notamment:

  • de donner accès à des opérations mathématiques de base comme la racine carrée, la trigonométrie, les logarithmes, etc.;
  • d'effectuer des opérations rapides sur des matrices multidimentionnelles (ndarray, ou n-dimensionnal array), dont des calculs d'algèbre linéaire;
  • d'effectuer des calculs élément par élément, ligne par ligne, colonne par colonne, etc., grâce à la "vectorisation" - par exemple en additionnant un scalaire à un vecteur, le scalaire sera additionné à tous les éléments du vecteur;
  • d'importer et exporter des fichiers de données;
  • de générer des nombres aléatoires selon des lois de probabilité.

SciPy

Basée sur NumPy, SciPy est une collection de fonctions mathématiques offrant une panoplie d'outil pour le calcul scientifique. Il simplifie certaines fonctions de Numpy, et offre des gadgets qui se rendront essentiels pour des opérations courrantes, notamment:

  • calcul intégral et résolution de systèmes d'équations différentielles ordinaires
  • interpolation entre coordonnées
  • traitement et analyse de signal

Note. Un bibliothèque portant le préfixe scikit fait partie de la trousse d'extensions de SciPy.

pandas

Les données sont souvent organisées sous forme de tableau, les colonnes représentant les variables mesurées et les lignes représentant les observations. La bibliothèque pandas offre un kit d'outil pour travailler avec des tableaux de données (DataFrame) de manière efficace. Avec une rapidité d'exécution héritée de NumPy, pandas inclut l'approche des bases de données relationnelles (SQL) pour filtrer, découper, synthétiser, formater et fusionner des tableaux.

matplotlib

Les graphiques sont des synthèses visuelles de données qui autrement seraient pénibles à interpréter. Malgré les récents développements en visualisation sur Python, matplotlib reste la bibliothèque de base pour la présentation de graphiques: nuages de points, lignes, boxplots, histogrammes, contours, etc. Il y en a d'autres comme altair, seaborn et bokeh, qui vous seront présentées au moment opportun.

Modules spécialisés: <<<À AJUSTER À LA FIN>>>

SymPy

Le calcul symbolique a une place théorique importante en calcul scientifique. SymPy sera utilisée pour valider des fonctions issues d'équations différentielles.

statsmodels

Plus que de la statistique, la bibliothèque statsmodels est conçue comme accompagnatrice dans l'analyse de données. Elle aidera à effectuer des statistiques comme des analyses de variance, des régressions et des analyses de survie, mais aussi des opérations de prétraitement comme l'imputation de données manquantes.

scikit-learn

L'apprentissage automatique (machine learning en anglais), permet de détecter des structures dans les données dans l'objectif de prédire une nouvelle occurance, que ce soit un ou plusieurs variables numériques (régression) ou catégorielles (classification). De nombreux algorhitmes sont appelés à être utilisés en sciences de la vie. scikit-learn est une trousse d'outil permettant d'appréhender ces outils complexes de manière efficace, conviviale et cohérente, en plus d'offir la possibilité d'empaqueter des machines d'apprentissage dans des logiciels. La documentation de scikit-learn est d'une rare qualité. scikit-learn peut aussi être utilisé pour effectuer des classifications non supervisées (classifier des données qui n'ont pas de catégorie prédéterminées), notamment l'analyse de partitionnement (clustering en anglais).

scikit-bio

scikit-bio sera utilisé principalement pour l'analyse compositionnelle et pour l'ordination. Ses possibilités ne s'arrêtent toutefois pas là. Techniquement, la bibliothèque scikit-bio a moins de lien avec scikit-learn qu'avec QIIME, un logiciel libre dédié à la bioinformatique, une discipline connexe au génie écologique, mais axée sur l'analyse génétique.

bokeh

Un graphique est une représentation visuelle de données. Bien que matplotlib un outil essentiel au calcul scientifique avec Python, de nombreuses autres bibliothèques ont été développées pour combler ses lacunes. L'une d'entre elle émerge du transfert de la publication traditionnelle (papier, puis pdf) vers la publication de documents interactifs. bokeh est une bibliothèque qui, parmi d'autres (notamment plotly et mpld3), offre la possibilité de créer des graphiques intéractifs. Bonus: bokeh est aussi une plateforme de développement de logiciels scientifiques.

ggplot

gg, pour Grammar of Graphics. C'est avant tout un langage pour exprimer le passage de la donnée à sa représentation graphique. Le module ggplot2 est l'un des plus prisés du langage R. Un groupe de travail a heureusement planché sur une version Python, moins complète mais hautement utile pour tracer des graphiques de manière conviviale autant pour l'exploration de données que pour la publication.

SfePy

Simple Finite Elements with Python est un gros module conçu pour appréhender de la manière la plus simple possible la modélisation d'équations différentielles partielles par éléments finis. Cette méthode, largement utilisée en ingénierie, sera utile pour modéliser une panoplie de mécanismes déterministes: les transferts d'énergie, l'écoulement de l'eau, le transport des solutés et la dispersion des espèces.

lifelines

Combien de temps reste-t-il avant un événment? C'est la question que pose l'analyste de survie. lifelines est un module Python conçu exactement pour cela.

Interfaces

On les appelle des interfaces graphiques ou des environnement intégrés de développement et son conçus pour faciliter l'utilisation d'un langage de programmation, souvent pour des applications particulières. Utiliser Python uniquement dans un terminal n'est pas très pratique pour garder la trace des calculs. Comme la plupart des interfaces conçus pour le calcul scientifique, Jupyter comporte trois composantes: un éditeur de commande, un moyen d'exécuter les commandes et un afficheur de graphiques.

Jupyter

Jupyter lab

Anciennement nommé IPython notebook, puis Jupyter notebook, Jupyter lab s'inspire d'un format usuelle en science: le carnet de laboratoire.

Jupyter lab fonctionne dans une fenêtre de navigateur internet. Le code est interprété par IPython, un interprétateur pour le calcul scientifique sur Python. Chaque cellule peut contenir un texte explicatif (édité en markdown, un outil de traitement de texte où le formattage est effectué dans texte à l'aide de caractères spéciaux), incluant des équations (écrites en format LaTeX via MathJax - il existe des éditeurs d'équations en ligne), ou des morceaux de code. Par ailleurs, ces notes de cours sont rédigées dans des carnets Jupyter.

nteract

Afin de libérer Jupyter du navigateur web, une équipe a développé le logiciel nteract, une version épurée de Jupyter en format d'application bureau. C'est l'interface que nous allons utiliser lors de ce cours. Téléchargez l'installateur et installez!

Autres

L'interface de Rodeo comprend des fenêtres pour l'édition de code, pour interprétateur IPython, pour la session de travail et pour afficher les graphiques. En fait, il imite l'interface de RStudio pour R. C'est une solution visuellement élégante et moderne, mais pas aussi complète que Spyder.

Spyder est un acronyme pour "Scientific PYthon Development EnviRonment". Si vous avez installé Anaconda, Spyder est déjà installé sur votre ordiateur. Il est comparable à Rodeo, mais est plus ancien, plus complet, mais aussi plus complexe.

Il existe aussi plusieurs autres environnements de développement en mode libre (Atom/Hydrogen, Eclipse/PyDev, Komodo IDE, Lighttable, Ninja IDE). Mais certaines préféreront seulement utiliser un bon éditeur texte (Atom, Brackets, LighttTable, Notepad++, etc.) accompagné d'un terminal sous IPython.

Astuces pour utiliser Jupyter

Ce manuel est créé avec Jupyter. En double-cliquant dans ses cellules de texte, vous aurez accès au code markdown, un langage HTML simplifié permettant d'insérer des titres, des tableaux, des emphases en italique et en gras, des équations, des liens, des citations, des encadrés, des listes, etc.

Cellule markdown

Formatter un texte en markdown est relativement facile. Vous utiliserez sans doute ces outils:

# Titre 1
## Titre 2
###### Titre 6

Formater du `code alligné`. Ou bien un

\

paragraphe dédié au code ```

Liste à puce

  • item 1
  • item 2
    • item 2.1
      • item 2.1.1

Liste numérotée

  1. item 1
  2. item 2
    1. item 2.1
      1. item 2.1.1

Texte emphasé en italique ou en gras.

Hyperlien

Insérer une image

Insérer une équation en ligne: $\alpha + \beta$. Ou en un paragraphe:

$$ c = \sqrt{\left( a^2 + b^2 \right)} $$
Symbole Format
Titre 1 # Titre 1
Titre 2 ## Titre 2
Titre 6 ###### Titre 6
code ligne `code`
code paragraphe ```code```
Items de liste à puce - item avec indentation pour les sous-items
Items de liste numérotée 0. item avec indentation pour les sous-items
Italique Texte emphasé en *italique*
Gras Texte emphasé en **gras**
Hyperlien Créer un [lien](https://python.org)
Image Insérer une image ![](....png)
Équation Insérer une équation en format LaTeX \$c = \sqrt \left( a^2 + b^2 \right)\$

```

Cellule de code

Il était suggéré au cours de ce chapitre d'entrer les commandes dans un terminal. À partir d'ici, il sera préférable d'utiliser un notebook à partir d'ici, et d'excécuter les calculs dans des cellules de code.


In [2]:
a = 5/2
a


Out[2]:
2.5