Nous allons voir dans ce complément comment créer des tableaux en plusieurs dimensions et manipuler la forme (shape) des tableaux.
import numpy as npUn exemple¶
Nous avons vu précédemment comment créer un tableau numpy de dimension 1 à partir d’un simple itérable, nous allons à présent créer un tableau à 2 dimensions, et pour cela nous allons utiliser une liste imbriquée :
d2 = np.array([[11, 12, 13], [21, 22, 23]])
d2array([[11, 12, 13],
[21, 22, 23]])Ce premier exemple va nous permettre de voir les différents attributs de tous les tableaux numpy.
L’attribut shape¶
Tous les tableaux numpy possèdent un attribut shape qui retourne, sous la forme d’un tuple, les dimensions du tableau :
# la forme (les dimensions) du tableau
d2.shape(2, 3)Dans le cas d’un tableau en 2 dimensions, cela correspond donc à lignes x colonnes.
On peut facilement changer de forme¶
Comme on l’a vu dans la vidéo, un tableau est en fait une vue vers un bloc de données. Aussi il est facile de changer la dimension d’un tableau - ou plutôt, de créer une autre vue vers les mêmes données :
# l'argument qu'on passe à reshape est le tuple
# qui décrit la nouvelle *shape*
v2 = d2.reshape((3, 2))
v2array([[11, 12],
[13, 21],
[22, 23]])Et donc, ces deux tableaux sont deux vues vers la même zone de données ; ce qui fait qu’une modification sur l’un se répercute dans l’autre :
# je change un tableau
d2[0][0] = 100
d2array([[100, 12, 13],
[ 21, 22, 23]])# ça se répercute dans l'autre
v2array([[100, 12],
[ 13, 21],
[ 22, 23]])Les attributs liés à la forme¶
Signalons par commodité les attributs suivants, qui se dérivent de shape :
# le nombre de dimensions
d2.ndim2# vrai pour tous les tableaux
len(d2.shape) == d2.ndimTrue# le nombre de cellules
d2.size6# vrai pour tous les tableaux
# une façon compliquée de dire
# une chose toute simple :
# la taille est le produit
# des dimensions
from operator import mul
from functools import reduce
d2.size == reduce(mul, d2.shape, 1)TrueLorsqu’on utilise reshape, il faut bien sûr que la nouvelle forme soit compatible :
try:
d2.reshape((3, 4))
except Exception as e:
print(f"OOPS {type(e)} {e}")OOPS <class 'ValueError'> cannot reshape array of size 6 into shape (3,4)
Dimensions supérieures¶
Vous pouvez donc deviner comment on construit des tableaux en dimensions supérieures à 2, il suffit d’utiliser un attribut shape plus élaboré :
shape = (2, 3, 4)
size = reduce(mul, shape)
# vous vous souvenez de arange
data = np.arange(size)d3 = data.reshape(shape)
d3array([[[ 0, 1, 2, 3],
[ 4, 5, 6, 7],
[ 8, 9, 10, 11]],
[[12, 13, 14, 15],
[16, 17, 18, 19],
[20, 21, 22, 23]]])Cet exemple vous permet de voir qu’en dimensions supérieures la forme est toujours :
n1 x n2 x ... x lignes x colonnes
Enfin, ce que je viens de dire est arbitraire, dans le sens où, bien entendu, vous pouvez décider d’interpréter les tableaux comme vous voulez.
Mais en termes au moins de l’impression par print, il est logique de voir que l’algorithme d’impression balaye le tableau de manière mécanique comme ceci :
for i in range(2):
for j in range(3):
for k in range(4):
array[i][j][k]Et c’est pourquoi vous obtenez la présentation suivante avec des tableaux de dimensions plus grandes :
# la même chose avec plus de dimensions
shape = (2, 3, 4, 5)
size = reduce(mul, shape) # le produit des 4 nombres dans shape
size120data = np.arange(size)
# ce tableau est visualisé
# à base de briques de base
# de 4 lignes et 5 colonnes
d4 = data.reshape(shape)
d4array([[[[ 0, 1, 2, 3, 4],
[ 5, 6, 7, 8, 9],
[ 10, 11, 12, 13, 14],
[ 15, 16, 17, 18, 19]],
[[ 20, 21, 22, 23, 24],
[ 25, 26, 27, 28, 29],
[ 30, 31, 32, 33, 34],
[ 35, 36, 37, 38, 39]],
[[ 40, 41, 42, 43, 44],
[ 45, 46, 47, 48, 49],
[ 50, 51, 52, 53, 54],
[ 55, 56, 57, 58, 59]]],
[[[ 60, 61, 62, 63, 64],
[ 65, 66, 67, 68, 69],
[ 70, 71, 72, 73, 74],
[ 75, 76, 77, 78, 79]],
[[ 80, 81, 82, 83, 84],
[ 85, 86, 87, 88, 89],
[ 90, 91, 92, 93, 94],
[ 95, 96, 97, 98, 99]],
[[100, 101, 102, 103, 104],
[105, 106, 107, 108, 109],
[110, 111, 112, 113, 114],
[115, 116, 117, 118, 119]]]])Vous voyez donc qu’avec la forme :
2, 3, 4, 5cela vous donne l’impression que vous avez comme brique de base des tableaux qui ont :
4 lignes
5 colonnesEt souvenez-vous que vous pouvez toujours insérer un 1 n’importe où dans la forme, puisque ça ne modifie pas la taille qui est le produit des dimensions :
d2.shape(2, 3)d2array([[100, 12, 13],
[ 21, 22, 23]])d2.reshape(2, 1, 3)array([[[100, 12, 13]],
[[ 21, 22, 23]]])d2.reshape(2, 3, 1)array([[[100],
[ 12],
[ 13]],
[[ 21],
[ 22],
[ 23]]])Ou même :
d2.reshape((1, 2, 3))array([[[100, 12, 13],
[ 21, 22, 23]]])d2.reshape((1, 1, 1, 1, 2, 3))array([[[[[[100, 12, 13],
[ 21, 22, 23]]]]]])Résumé des attributs¶
Voici un résumé des attributs des tableaux numpy :
| attribut | signification | exemple |
|---|---|---|
shape | tuple des dimensions | (3, 5, 7) |
ndim | nombre dimensions | 3 |
size | nombre d’éléments | 3 * 5 * 7 |
dtype | type de chaque élément | np.float64 |
itemsize | taille en octets d’un élément | 8 |
Divers¶
Je vous signale enfin, à titre totalement anecdotique cette fois, l’existence de la méthode ravel qui vous permet d’aplatir n’importe quel tableau :
d2array([[100, 12, 13],
[ 21, 22, 23]])d2.ravel()array([100, 12, 13, 21, 22, 23])# il y a d'ailleurs aussi flatten qui fait
# quelque chose de semblable
d2.flatten()array([100, 12, 13, 21, 22, 23])