Introduction à pour Calcul Scientifique - Statistique

Résumé Présentation de pyhton, exécution de commandes interactives ou de scripts avec un IDE, utilisation d'un calepin; les types et structures élémentaires de données, les structures de contrôle, les fonctions, classes et modules. Introduction à l'utilisation des librairies scientifiques: Numpy, Matplotlib, Scipy et au type array.

1 Introduction

1.1 Prérequis

Ce calepin introduit le langage libre Python et décrit les premières commandes nécessaires au pré-traitement des données avant l'utilisation de méthodes statistiques avec ce langage ou avec R. Les aspects statistiques développés dans les différentes vignettes de Wikistat sont supposés acquis ainsi qu'une connaissance des principes élémentaires de programmation dans un langage matriciel comme R ou Matlab.

Pour des approfondissements, il existe de très nombreuses ressources pédagogiques accessibles sur la toile dont le tutoriel officiel de Python 3.4., les sites pythontutor.com, courspython.com, le livre de Sheppard (2014) qui présentent une introduction à Python pour l'\'Econométrie et la Statistique et celui de Mac Kinney (2013), principal auteur de la bibliothèque pandas.

1.2 Installation

Python et ses librairies peuvent être installés dans quasiment tout environnement matériel et système d'exploitation à partir du site officiel. Voici les principales librairies scientifiques définissant des structures de données et fonctions de calcul indispensables.

  • ipython: pour une utilisation interactive de Python,
  • numpy: pour utiliser vecteurs et tableaux,
  • scipy: intègre les principaux algorithmes numériques,
  • matplotlib: pour les graphes,
  • pandas: structure de données et feuilles de calcul,
  • patsy: formules statistiques,
  • statsmodels: modélisation statistique,
  • seaborn: visualisation de données,
  • scikit-learn: algorithmes d'apprentissage statistique.

Néanmoins, compte tenu de la complexité de l'opération, il est plus simple pour le néophyte, surtout sous Windows, de faire appel à une procédure d'installation intégrant les principales librairies. Ces procédures sont développées par des entreprises commerciales mais libres de droits pour une utilisation académique.

  • Continuum Analytics propose Anaconda avec au choix la version 3.4 ou celle 2.7. Conda est l'utilitaire (commande en ligne) qui permet les mises à jour et installations des librairies complémentaires.
  • Enthought propose Canopy qui n'installe pour le moment que la version 2.7 et intègre un package manager avec interface graphique. Attention, certaines librairies même "collectives" ne sont disponibles que dans la version commerciale ou celle "académique" de Canopy après inscription.

D'un point de vue légal, les propositions sont identiques mais Canopy nécessite la création d'un compte académique. Seul "souci", ces versions n'incluent que les versions dites stables des différentes librairies et donc avec un temps de retard vis-à-vis des versions encore développement.

C'est Anaconda qui est utilisée ici, car préférable pour un poste personnel, en version 2.7; C'est aussi la version installée par le CSN de l'INSA dans les salles de TP.

2 Utilisation de Python

Python exécute programmes ou scripts, programmes qui peuvent être pré-compilés pour plus d'efficacité. Ce langage s'exécute également à l'aide d'un interprète de commande (IDLE) ou {IPython) de manière interactive. En situation pédagogique, c'est l'utilisation et la réalisation d'un notebook Ipython (calepin) ou plutôt maintenant Jupyter qui est privilégiée à partir d'un simple navigateur (éviter internet explorer).

2.1 Calepin Jupyter

Les commandes sont regroupées dans des cellules suivies de leur résultat après exécution. Ces résultats et commentaires sont stockés dans un fichier spécifique .ipynb et sauvegardés. Les commandes LaTeX sont acceptées pour intégrer des formules, la mise en page est assurée par des balises HTML ou Markdown.

La commande de sauvegarde permet également d'extraire les seules commandes Python dans un fichier d'extension .py. C'est une façon simple et efficace de conserver tout l'historique d'une analyse pour en faire une présentation ou créer un tutoriel. Le calepin peut être en effet chargé sous un autre format: page html, fichier .pdf ou diaporama.

Le projet Jupyter propose cet environnement de calepin pour beaucoup de langages (Pyhton, Julia, Scala...) dont R. Il devient un outil indispensable pour assurer simplement la reproductibilité des analyses.

L'ouverture d'un navigateur sur un calepin (Ipython ou Jupyter) est obtenu, selon l'installation, à partir des menus ou en exécutant: jupyter notebook ou ipython notebook dans une fenêtre de commande. Une fois le calepin ouvert,

  • Entrer des commandes Python dans une cellule,
  • Cliquer sur le bouton d'exécution de la cellule.
  • Ajouter une ou des cellules de commentaires et balises HTML ou Markdown. Itérer l'ajout de cellules. Une fois l'exécution terminée:
  • Sauver le calepin .ipynb
  • Charger éventuellement une version .html pour une page web.
  • Charger le fichier .py regroupant les commandes python pour une version opérationnelle.

Attention Un calepin de IPython ou Jupyter est un outil de travail exploratoire efficace et un compte rendu nécessairement chronologique d'exécution; ce n'est pas le rapport d'une étude statistique dont l'organisation suit des règles spécifiques.

2.2 IDE Spyder

Pour la réalisation d'applications et programmes plus complexes, l'usage d'un IDE (integrated Development Environment) libre comme Spyder est recommandé. Ce dernier est intégré à la distribution Anaconda et sa présentation proche de celles de Matlab ou RStudio. Cet environnement exécutant IPython reconnaît évidemment les commandes précédentes.

Comme pour RStudio, Spider ouvre plusieurs fenêtres:

  • un éditeur de commandes dont les boutons du menu exécutent tout le fichier ou interactivement la cellule courante, sauvent le fichier, contrôlent le débogage. Une cellule débute par la balise: #%%.
  • Un explorateur d'objets avec aide en ligne, des variables en cours, du répertoire courant. Les boutons de l'explorateur de variables permettent de supprimer, sauver les objets créés ou encore d'importer des données.
  • La console IPython avec les résultats et son historique.

2.3 Exemple

En résumé, utiliser un calepin pour des analyses exploratoires élémentaires et un IDE Spyder ou Eclipse (un peu compliqué!) pour la construction de programmes et modules.

Selon l'installation et à partir du répertoire de travail, exécuter la commande:

jupyter notebook

qui ouvre le navigateur par défaut.

Sur les postes géré par le CSN de l'INSA, si cela ne marche pas, il peut être nécessaire d'ajouter une variable d'environnement:

export PATH=/usr/local/insa/anaconda/bin:$PATH

Entrer les commandes ci-dessous dans le calepin et les exécuter cellule par cellule en cliquant sur le bouton d'exécution de la cellule courante.


In [ ]:
# Ceci est le début d'une session Python gérée à l'aide d'un calepin.
# Le script est divisé en cellules avec généralement l'affichage d'au plus un résultat par cellule.
## Importer les librairies nécessaires 
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
from pylab import *
import os 
## Définir si nécessaire le répertoire courant spécifique 
##  à l'utilisateur
os.chdir(r'.')
## Commande magique pour obtenir les graphiques dans le calepin
%matplotlib inline

In [ ]:
#%% Créer un data frame avec pandas
data = pd.DataFrame({
    'Gender': ['f', 'f', 'm', 'f', 'm', 'm', 'f', 'm', 'f', 'm'],
    'TV': [3.4, 3.5, 2.6, 4.7, 4.1, 4.0, 5.1, 4.0, 3.7, 2.1]})
data

In [ ]:
# Génération de variables aléatoires gaussiennes
xx = randn(100,100)
y = mean(xx,0)
# graphique
plot(y)
show()

3. Types de données

3.1 Scalaires et chaînes

La déclaration des variables est implicite ({integer, float, boolean, string), la syntaxe est très proche de celle de R mais il n'y a pas de type factor.


In [ ]:
a=3  # est un entier
b=1. # est un flottant
# Attention:
a/2  # a pour résultat 1.5 en Python 3.4 
     # mais 1 en 2.7

Opérateurs de comparaison : ==, >, <, != de résultat booléen.


In [ ]:
# Comparaison
a==b

In [ ]:
#  affichage et type des variables
type(a)

In [ ]:
# Chaîne de caractère
a='bonjour '
b='le '
c='monde'
a+b+c

Attention à l'encodage des caractères. Ce n'est pas le même en python 2 (ascii) et python 3 (utf-8). Ce n'est pas fait dans ces exemples élémentaires mais il est vivement recommander de gérer systématiquement des textes complexes avec caractères spéciaux (accents, guillements...) en utf-8


In [ ]:
a=u'bonjour' # encodage utf-8
type(a)

In [ ]:
a='bonjour'  # encodage ascii
type(a)

3.2 Structures de base

Listes

Les listes permettent des combinaisons de types. Attention, le premier élément d'une liste ou d'un tableau est indicé par 0, pas par 1.


In [ ]:
# exemples de listes
liste_A = [0,3,2,'hi']
liste_B = [0,3,2,4,5,6,1]
liste_C = [0,3,2,'hi',[1,2,3]]    
# Elément d'une liste 
liste_A[1]

In [ ]:
liste_C[-1] #  dernier élément

In [ ]:
liste_C[-1][0]

In [ ]:
liste_C[-2]

In [ ]:
liste_B[0:2] #  Sous-liste

In [ ]:
liste_B[0:5:2]  # début:fin:pas

In [ ]:
liste_B[::-1]

In [ ]:
# Fonctions de listes
List=[3,2,4,1]
List.sort() 
print(List)

In [ ]:
List.append('hi')
print(List)

In [ ]:
List.count(3)

In [ ]:
List.extend([7,8,9])
print(List)

In [ ]:
List.append([10,11,12])
print(List)

t-uple

Un tuple est similaire à une liste mais ne peut être modifié, il est défini par des parenthèses.


In [ ]:
MyTuple=(0,3,2,'h')
MyTuple[1]

In [ ]:
MyTuple[1]=10 # TypeError: "tuple" object

Dictionnaire

Un dictionnaire est similaire à une liste mais chaque entrée est assignée par une clé / un nom, il est défini avec des accolades. Cet objet est utilisé pour la construction de l'index des colonnes (variables) du type DataFrame de la librairie pandas.


In [ ]:
months = {'Jan':31 , 'Fev': 28, 'Mar':31}
months['Jan']

In [ ]:
months.keys()

In [ ]:
months.values()

In [ ]:
months.items()

4. Syntaxe de Python

4.1 Structures de contrôle élémentaires

Un bloc de commandes ou de codes est défini par deux points suivis d'une indentation fixe. Cela oblige à l'écriture de codes faciles à lire mais à être très attentif sur la gestion des indentations car la fin d'indentation signifie la fin d'un bloc de commandes.

Structure conditionnelle


In [ ]:
# si alors sinon
a=2
if a>0:
    b=0
    print(b)
else:
    b=-1
print(b)

Structure itérative


In [ ]:
for i in range(4):
    print(i)

In [ ]:
for i in range(1,8,2):
    print(i)

In [ ]:
# Définition d'une fonction
def pythagorus(x,y):
    """ Calcule l'hypotenuse d'un triangle """
    r = pow(x**2+y**2,0.5)
    return x,y,r
pythagorus(3,4)

4.2 Fonctions


In [ ]:
# exemple d'appel
pythagorus(x=3,y=4)

In [ ]:
# aide intégrée
help(pythagorus)

In [ ]:
pythagorus.__doc__

In [ ]:
# Valeurs des paramètres par défaut
def pythagorus(x=1,y=1):
    """ calcule l'hypoténuse d'un triangle """
    r = pow(x**2+y**2,0.5)
    return x,y,r
pythagorus()

4.4 Modules et librairies

Modules

Un module contient plusieurs fonctions et commandes qui sont regroupées dans un fichier d'extension .py. Insérer un fichier vide de nom _init_.py dans chaque dossier et sous-dossier contenant un module à importer. Un module est appelé par la commande import. Un module est considéré comme un script s'il contient des commandes. Lors de l'import d'un script, les commandes sont exécutées tandis que les fonctions sont seulement chargées.

Commencer par définir un module dans un fichier texte contenant les commandes suivantes.

def DitBonjour(): print("Bonjour") def DivBy2(x): return x/2

Sauver le fichier avec pour nom testM.py dans le répertoire courant.

Il est possible d'importer toutes les fonctions en une seule commande import.


In [ ]:
import testM
testM.DitBonjour()

In [ ]:
print(testM.DivBy2(10))

In [ ]:
from testM import *
DitBonjour()

In [ ]:
print(DivBy2(10))

Ou seulement celles qui seront utilisées. Préférer cette dernière méthode pour les grosses librairies.


In [ ]:
import testM as tm
tm.DitBonjour()

In [ ]:
print(tm.DivBy2(10))
# délétion des objets
%reset

In [ ]:
from testM import DitBonjour
DitBonjour()

In [ ]:
print(DivBy2(10)) # erreur

Lors de son premier appel, un module est pré-compilé dans un fichier .pyc qui est utilisé pour les appels suivants. Attention, si le fichier a été modifié / corrigé, il a besoin d'être rechargé par la commande reload(name).

Une librairie (package) regroupe plusieurs modules dans différents sous-répertoires. Le chargement spécifique d'un des modules se fait en précisant le chemin. import sound.effects.echo

5. Calcul scientifique

Voici trois des principales librairies indispensables au calcul scientifique. Deux autres librairies: pandas, scikit-learn, sont exposées en détail dans des calepins spécifiques.

5.1 Principales librairies ou packages

NumPy

Cette librairie définit le type de données array ainsi que les fonctions de calcul qui y sont associées. Il contient aussi quelques fonctions d'algèbre linéaire et statistiques. Il n'est finalement utilisé que pour la définition du type array car les fonctions numériques sont beaucoup plus développées dans SciPy.

Matplotlib

Celle-ci propose des fonctions de visualisation / graphs avec des commandes proches de celles de Matlab. Aussi connue sous le nom de pylab. La gallerie de cette librairie propose tout un ensemble d'exemples de graphiques avec le code Python pour les générer.


In [ ]:
# Importation
import numpy as np
from pylab import *
gaussian = lambda x: np.exp(-(0.5-x)**2/1.5)
x=np.arange(-2,2.5,0.01)
y=gaussian(x)
plot(x,y)
xlabel("x values")
ylabel("y values")
title("Gaussian function")
show()

SciPy

Cette librairie est un ensemble très complet de modules d'algèbre linéaire, statistiques et autres algorithmes numériques. Le site de la documentation en fournit la liste.

5.2 Type Array

C'est de loin la structure de données la plus utilisée pour le calcul scientifique sous Python. Elle décrit des tableaux ou matrices multi-indices de dimension $ n = 1, 2, 3, \ldots , 40$. Tous les éléments sont de même type (booléen, entier, réel, complexe).

Il est possible de contrôler précisément le type d'un array, par exemple pour gagner de la place en mémoire, en codant les entiers sur 8, 16, 32 ou 64 bits, de même pour les réels (float) ou les complexes.

Les tableaux ou tables de données (data frame), bases d'analyses statistiques et regroupant des objets de types différents sont décrits avec la librairie pandas.

Définition du type array


In [ ]:
# Importation
import numpy as np
my_1D_array = np.array([4,3,2])
print(my_1D_array)

In [ ]:
my_2D_array = np.array([[1,0,0],[0,2,0],[0,0,3]])
print(my_2D_array)

In [ ]:
myList=[1,2,3]
my_array = np.array(myList)
print(my_array)

In [ ]:
a=np.array([[0,1],[2,3],[4,5]])
a[2,1]

In [ ]:
a[:,1]

Fonctions de type array


In [ ]:
np.arange(5)

In [ ]:
np.ones(3)

In [ ]:
np.ones((3,4))

In [ ]:
np.eye(3)

In [ ]:
np.linspace(3, 7, 3)

In [ ]:
np.mgrid[0:3,0:2]

In [ ]:
D=np.diag([1,2,4,3])
print(D)
print(np.diag(D))

In [ ]:
M=np.array([[10*n+m for n in range(3)] 
for m in range(2)]) 
print(M)

Le module numpy.random fournit toute une liste de fonctions pour la génération de matrices aléatoires.


In [ ]:
from numpy import random
random.rand(4,2) #tirage uniforme

In [ ]:
random.randn(4,2) #tirage selon la loi N(0,1)

In [ ]:
v=random.randn(1000)
import matplotlib.pyplot as plt
h=plt.hist(v,20) # histogramme à 20 pas
show()

In [ ]:
A=random.randn(64,64)
plt.imshow(A,interpolation="nearest")
plt.colorbar
plt.show()

In [ ]:
# Sauver, écrire dans un fichier, lire un fichier
M=random.randn(10,10)
np.savetxt('data.csv',M,fmt='%2.2f',delimiter=',')
#au format propre à numpy : npy

In [ ]:
np.save('data.npy',M)
np.load('data.npy')

Slicing


In [ ]:
v=np.array([1,2,3,4,5])
print(v)

In [ ]:
v[1:4]

In [ ]:
v[1:4:2]

In [ ]:
v[::]

In [ ]:
v[ : :2] # par pas de 2

In [ ]:
v[ : 3]

In [ ]:
v[3 :] # à partir de l'indice 3

In [ ]:
v[-1] # dernier élément

In [ ]:
v[-2 :] # deux derniers éléments

In [ ]:
M=random.rand(4,3) 
print(M)

In [ ]:
ind=[1,2]
M[ind] # lignes d'indices 1 et 2

In [ ]:
M[:,ind] # colonnes d'indices 1 et 2

In [ ]:
M[[0,2],[1,2]] # renvoie M[0,1] et M[2,2]

In [ ]:
M[np.ix_([0,2],[1,2])]

In [ ]:
(M>0.5)

In [ ]:
M[M>0.5]

Autres fonctions


In [ ]:
a=np.array([[0,1],[2,3],[4,5]])
np.ndim(a) # Nombre de dimensions)

In [ ]:
np.size(a) # Nombre d’éléments

In [ ]:
np.shape(a) # Tuple contenant la dimension de a

In [ ]:
np.transpose(a) # Transposée

In [ ]:
a.T # autre façon de définir la transposée

In [ ]:
a.min(), np.min(a)  # Valeur min

In [ ]:
a.sum(), np.sum(a)  # Somme des valeurs

In [ ]:
a.sum(axis=0)  # Somme sur les colonnes

In [ ]:
a.sum(axis=1)  # sur les lignes

Quelques manipulations:


In [ ]:
np.r_[1:4,10,11]  # Concaténation en ligne

In [ ]:
np.c_[1:4,11:14]  # Concaténation en colonne

In [ ]:
np.c_[1:4,11:15]  # erreur

In [ ]:
np.arange(6).reshape(3,2)

In [ ]:
A=np.array([[1,2],[3,4]])
np.tile(A,(3,2)) # Répétition de la matrice A

In [ ]:
A=np.array([[1,2],[3,4]])
B=np.array([[11,12],[13,14]])
#Concaténation en ligne
np.concatenate((A,B),axis=0)

In [ ]:
# Equivalent à
np.vstack((A,B))

In [ ]:
# Concaténation en colonne
np.concatenate((A,B),axis=1)

In [ ]:
# Equivalent à
np.hstack((A,B))

Opérations sur les arrays


In [ ]:
# somme
a=np.arange(6).reshape(3,2)
b=np.arange(3,9).reshape(3,2)
c=np.transpose(b)
a+b

In [ ]:
a*b # produit terme à terme

In [ ]:
np.dot(a,c) # produit matriciel

In [ ]:
np.power(a,2)

In [ ]:
np.power(2,a)

In [ ]:
a/3

Les fonctions genfromtxt, avetxt permettent de lire, écrire des fichiers textes par exemple au format .csv mais ces fonctionnalités sont plus largement abordées avec la librairie pandas.

Fonctions d'algèbre linéaire


In [ ]:
# Importation
import numpy as np
from scipy import linalg
A = np.array([[1,2],[3,4]])
linalg.inv(A)

In [ ]:
linalg.det(A)

In [ ]:
la,v = linalg.eig(A)
l1,l2 = la
# valeurs propres
print(l1, l2)

In [ ]:
# 1er vecteur propre
print(v[:,0])

In [ ]:
# SVD de A
U,s,V = linalg.svd(A) 
print(s**2)

In [ ]:
linalg.eig(np.dot(np.transpose(A),A))

Tests élémentaires de Statistique


In [ ]:
# Importation
import scipy.stats
rvs1 = scipy.stats.norm.rvs(loc=5, scale=10,size=500)
rvs2 = scipy.stats.norm.rvs(loc=5, scale=10,size=500)
rvs3 = scipy.stats.norm.rvs(loc=8, scale=10,size=500)
# t-test returns: t-statistic/two-tailed p-value
scipy.stats.ttest_ind(rvs1, rvs2)

In [ ]:
scipy.stats.ttest_ind(rvs1, rvs3)

In [ ]:
# Kolmogorov-Smirnov test
# returns: KS statistic / two-tailed p-value
scipy.stats.ks_2samp(rvs1, rvs2)

In [ ]:
scipy.stats.ks_2samp(rvs1, rvs3)

Références

Mac Kinney W. (2013). Python for Data Analysis, O’Reilly. pdf

Sheppard K. (2014). Introduction to Python for Econometrics, Statistics and Data Analysis, pdf