import numpy as np
Regardons comment extraire des morceaux d'un tableau ou modifier seulement certaines de ses parties. Pour cela nous disposons de deux outils :
- l'extraction suivant les indices
- l'extraction suivant un filtre logique sur les valeurs
Filtrer via les indices¶
On peut extraire des valeurs d'un tableau en fonction de ses indices comme on l'a fait pour les listes. Pour chaque dimension du tableau on peut indiquer
- la valeur de l'indice voulu (un entier)
- une liste d'indices
debut:fin:saut
. Ainsi1:6:2
veut dire les valeurs impaires entre l'indice 1 et l'indice 6 exclus. Les valeursdebut
,fin
etsaut
sont optionnelles ::5
donne les 5 première valeurs (indices 0,1,2,3 et 4)3:
donne de la 4-ième à la dernière valeurs::3
donne une valeur sur 3 du début à la fin du tableau.
- une liste d'indices explicite comme
[1,3,-2]
(les valeurs négatives commencent par la fin,-2
est l'avant dernier indice)
a = np.arange(12).reshape(3,4)
print(a, '\n')
print(a[1, :], '\n') # 2nd line
print(a[0:2, 0:2], '\n') # top left sub-matrix
print(a[::2, -1], '\n') # even lines, last column
print(a[:, [0,-1]]) # first and last column
[[ 0 1 2 3] [ 4 5 6 7] [ 8 9 10 11]] [4 5 6 7] [[0 1] [4 5]] [ 3 11] [[ 0 3] [ 4 7] [ 8 11]]
Il est ainsi possible d'indiquer qu'une opération ne s'applique qu'à un extrait du tableau en indiquant quelles sont les cases du tableau qui seront modifiées :
a[::2, 1::2] += 100
a
array([[ 0, 101, 2, 103], [ 4, 5, 6, 7], [ 8, 109, 10, 111]])
Cela permet aussi d'écrire simplement des calculs comme extraire une image en niveau de gris d'une image en couleur :
image = np.random.randint(256, size=(800, 600, 3)) # RGB 800x600 image
gray_image = 0.2126 * image[:,:,0] + 0.7152 * image[:,:,1] + 0.0722 * image[:,:,2]
On peut aussi utiliser ...
pour remplacer plusieurs indices ainsi image[...,0] == image[:,:,0]
Les filtres logiques¶
Un filtre = une condition logique¶
Numpy permet d'extraire simplement les valeurs qui répondent à une condition logique.
Pour cela on utilise un filtre, à savoir un tableau booléen que l'on pose sur un tableau de même dimension en imaginant que les cases True sont des fenêtres et False des murs. Le résultat est l'ensemble des valeurs qu'on voit à travers les fenêtres ordonnées par leur indice.
Le résultat est toujours un tableau en 1 dimension sauf si on utilise where
.
a = np.arange(12).reshape(3,4)
fil = a > 5 # a > 5 means all VALUES greater than 5
print("The filter a > 5 is\n", fil)
a[fil] # apply the filter and show the result (1D array)
The filter a > 5 is [[False False False False] [False False True True] [ True True True True]]
array([ 6, 7, 8, 9, 10, 11])
Il est bien plus simple et lisible d'écrire la condition logique là où on met normalement les indices, à savoir entre les crochets :
a[a>5]
array([ 6, 7, 8, 9, 10, 11])
Lorsque le but est le filtre¶
Le filtre peut servir à autre chose qu'a séléctionner les valeurs de notre tableau. Il peut être le résultat sur lequel on veut travailler, par exemple pour une population fil = (age == weight)
. C'est un tableau de booléen qui donne des cas vrai et d'autre faux c.a.d. des 0 et des 1.
Ainsi, avec un filtre fil
, on peut savoir
combien de cas sont vrai : | fil.sum() |
|
s'il y a au moins un cas vrai : | fil.sum() > 0 |
Numpy offre aussi np.any(fil) |
si tous les cas sont vrai : | fil.prod() == 1 |
Numpy offre aussi np.all(fil) |
si au moins un cas est faux : | fil.prod() == 0 |
|
si tous les cas sont faux : | fil.sum() == 0 |
np.where(a > 5, a, 0) # if a > 5 then a else 0
array([[ 0, 0, 0, 0], [ 0, 0, 6, 7], [ 8, 9, 10, 11]])
On peut faire tous les filtres imaginables qui donnent un tableau de booléan.
np.where(a%3 == 0, 2*a, -1) # if a modulo 3 is 0 then 2 times a else -1
array([[ 0, -1, -1, 6], [-1, -1, 12, -1], [-1, 18, -1, -1]])
Mettre à jour un tableau avec un filtre¶
Une autre facon de conserver la forme du tableau consiste à ne modifier que les valeurs qui correspondent au filtre.
a = np.arange(12).reshape(3,4)
a[a > 5] = 200
a
array([[ 0, 1, 2, 3], [ 4, 5, 200, 200], [200, 200, 200, 200]])
Voici comment ajouter 100 à toutes les valeurs du tableau qui sont des carrés parfait ainsi qu'à la valeur 5 :
a = np.arange(12).reshape(3,4)
a[(np.round(np.sqrt(a)) - np.sqrt(a) == 0) | (a==5)] += 100 # | is OR (AND is &)
a
array([[100, 101, 2, 3], [104, 105, 6, 7], [ 8, 109, 10, 11]])
{{ PreviousNext("np01 Numpy Introduction.ipynb", "np03 Manipulations.ipynb")}}