import numpy as np
1 Introduction
Ce chapitre constitue une introduction à Numpy pour
s’assurer que les bases du calcul vectoriel avec Python
soient maîtrisées. La première partie du chapitre
présente des petits exercices pour pratiquer quelques fonctions basiques de Numpy
. La fin du chapitre présente
des exercices pratiques d’utilisation de Numpy
plus approfondis.
Il est recommandé de régulièrement se référer à la cheatsheet numpy et à la doc officielle en cas de doute sur une fonction.
Dans ce chapitre, on ne dérogera pas à la convention qui s’est imposée
d’importer Numpy
de la
manière suivante :
Nous allons également fixer la racine du générateur aléatoire de nombres afin d’avoir des résultats reproductibles :
import numpy as np
= np.random.default_rng(seed=12345) rng
Historiquement, la génération de nombres aléatoires se faisait pas le biais du package numpy.random
. Néanmoins, les auteurs de Numpy
recommandent maintenant d’utiliser plutôt des générateurs pour cela. Les exemples de ce tutoriel adoptent donc cette pratique.
2 Le concept d’array
Dans le monde de la science des données, comme cela sera évoqué plus en profondeur dans les prochains chapitres, l’objet central est le tableau à deux dimensions de données. La première correspond aux lignes et la seconde aux colonnes. Si on ne se préoccupe que d’une dimension, on se rapporte à une variable (une colonne) de notre tableau de données. Il est donc naturel de faire le lien entre les tableaux de données et l’objet mathématique que sont les matrices et les vecteurs.
NumPy
(Numerical Python
) est la brique de base
pour traiter des listes numériques ou des chaines
de textes comme des matrices.
NumPy
intervient pour proposer
ce type d’objets, et
les opérations standardisées associées qui n’existent
pas dans le langage Python
de base.
L’objet central de NumPy
est
l’array
qui est un tableau de données multidimensionnel.
L’array Numpy
peut être unidimensionnel et s’apparenter à un
vecteur (1d-array
),
bidimensionnel et ainsi s’apparenter à une matrice (2d-array
) ou,
de manière plus générale,
prendre la forme d’un objet
multidimensionnel (Nd-array
), sorte de tableau emboîté.
Les tableaux simples (uni ou bi-dimensionnels) sont faciles à se représenter
et représentent la majorité des besoins liés à Numpy
.
Nous découvrirons lors du chapitre suivant, sur Pandas
, qu’en pratique
on manipule rarement directement Numpy
qui est une librairie
bas niveau.
Un DataFrame Pandas
sera construit à partir d’une collection
d’array uni-dimensionnels (les variables de la table), ce qui permettra d’effectuer des opérations cohérentes
(et optimisées) avec le type de la variable.
Avoir quelques notions Numpy
est utile pour comprendre
la logique de manipulation vectorielle
rendant les traitements sur des données plus lisibles,
plus efficaces et plus fiables.
Par rapport à une liste,
- un array ne peut contenir qu’un type de données (
integer
,string
, etc.), contrairement à une liste. - les opérations implémentées par
Numpy
seront plus efficaces et demanderont moins de mémoire
Les données géographiques constitueront une construction un peu plus complexe qu’un DataFrame
traditionnel.
La dimension géographique prend la forme d’un tableau plus profond, au moins bidimensionnel
(coordonnées d’un point). Néanmoins, les librairies de manipulation
de données géographiques permettront de ne pas se préoccuper de
cette complexité accrue.
2.1 Créer un array
On peut créer un array de plusieurs manières. Pour créer un array à partir d’une liste,
il suffit d’utiliser la méthode array
:
1,2,5]) np.array([
array([1, 2, 5])
Il est possible d’ajouter un argument dtype
pour contraindre le type du array :
"a","z","e"],["r","t"],["y"]], dtype="object") np.array([[
array([list(['a', 'z', 'e']), list(['r', 't']), list(['y'])], dtype=object)
Il existe aussi des méthodes pratiques pour créer des array:
- séquences logiques :
np.arange
(suite) ounp.linspace
(interpolation linéaire entre deux bornes) ; - séquences ordonnées : array rempli de zéros, de 1 ou d’un nombre désiré :
np.zeros
,np.ones
ounp.full
; - séquences aléatoires : fonctions de génération de nombres aléatoires :
rng.uniform
,rng.normal
, etc. oùrng
est un générateur de nombre aléatoires ;
- tableau sous forme de matrice identité :
np.eye
.
Ceci donne ainsi, pour les séquences logiques:
0,10) np.arange(
array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
0,10,3) np.arange(
array([0, 3, 6, 9])
0, 1, 5) np.linspace(
array([0. , 0.25, 0.5 , 0.75, 1. ])
Pour un array initialisé à 0:
10, dtype=int) np.zeros(
array([0, 0, 0, 0, 0, 0, 0, 0, 0, 0])
ou initialisé à 1:
3, 5), dtype=float) np.ones((
array([[1., 1., 1., 1., 1.],
[1., 1., 1., 1., 1.],
[1., 1., 1., 1., 1.]])
ou encore initialisé à 3.14:
3, 5), 3.14) np.full((
array([[3.14, 3.14, 3.14, 3.14, 3.14],
[3.14, 3.14, 3.14, 3.14, 3.14],
[3.14, 3.14, 3.14, 3.14, 3.14]])
Enfin, pour créer la matrice \(I_3\):
3) np.eye(
array([[1., 0., 0.],
[0., 1., 0.],
[0., 0., 1.]])
Générer:
- \(X\) une variable aléatoire, 1000 répétitions d’une loi \(U(0,1)\)
- \(Y\) une variable aléatoire, 1000 répétitions d’une loi normale de moyenne nulle et de variance égale à 2
- Vérifier la variance de \(Y\) avec
np.var
3 Indexation et slicing
3.1 Logique dans le cas d’un array unidimensionnel
La structure la plus simple est l’array unidimensionnel:
= np.arange(10)
x print(x)
[0 1 2 3 4 5 6 7 8 9]
L’indexation est dans ce cas similaire à celle d’une liste:
- le premier élément est 0
- le énième élément est accessible à la position \(n-1\)
La logique d’accès aux éléments est ainsi la suivante :
x[start:stop:step]
Avec un array unidimensionnel, l’opération de slicing (garder une coupe du array) est très simple. Par exemple, pour garder les K premiers éléments d’un array, on fera:
-1)] x[:(K
En l’occurrence, on sélectionne le K\(^{eme}\) élément en utilisant
-1] x[K
Pour sélectionner uniquement un élément, on fera ainsi:
= np.arange(10)
x 2] x[
np.int64(2)
Les syntaxes qui permettent de sélectionner des indices particuliers d’une liste fonctionnent également avec les arrays.
Prenez x = np.arange(10)
et…
- Sélectionner les éléments 0, 3, 5 de
x
- Sélectionner les éléments pairs
- Sélectionner tous les éléments sauf le premier
- Sélectionner les 5 premiers éléments
10) np.arange(
array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
La logique se généralise pour les array multidimensionnels. L’indexation se fait alors à plusieurs niveaux. Prenons par exemple un array à 2 dimensions (une matrice en quelques sortes):
Si on veut sélectionner la 2e ligne, 3e colonne (l’élément de valeur 6), on fait
np.int32(6)
Maintenant, pour sélectionner une colonne complète (par exemple la 2e), on peut utiliser le 2e index pour spécifier celle-ci (index 1 en Python puisque l’indexation part de 0) puis :
sur la première dimension (version raccourcie de 0:N
) pour ne pas discriminer selon cette dimension:
array([2, 5], dtype=int32)
Le principe se généralise, mais se complexifie, pour des array imbriqués. Heureusement, ce sont des objets qu’on manipule assez rarement directement, la plupart de nos données numériques étant des tableaux plats (une valeur - l’observation - est le croisement d’une ligne - l’individu - et d’une colonne - la variable).
Citation
@book{galiana2023,
author = {Galiana, Lino},
title = {Python pour la data science},
date = {2023},
url = {https://pythonds.linogaliana.fr/},
doi = {10.5281/zenodo.8229676},
langid = {fr}
}