Comment remodeler les tableaux NumPy en Python



Dans ce guide pratique, vous apprendrez à manipuler la fonction reshape() de NumPy pour modifier la structure des tableaux sans altérer les données initiales.

Lorsque vous travaillez avec des tableaux NumPy, il est fréquent de vouloir ajuster leurs dimensions. Cette transformation est particulièrement utile lors du traitement de données en plusieurs étapes.

Heureusement, la fonction reshape() de NumPy facilite grandement cette tâche. Au cours des prochaines minutes, vous découvrirez sa syntaxe et comment remodeler des tableaux avec différentes dimensions.

Qu’est-ce que le remodelage de tableaux NumPy ?

Il arrive souvent, lors de l’utilisation de tableaux NumPy, de commencer par créer un tableau de nombres à une dimension, puis de vouloir le transformer en un tableau avec une dimension différente.

Cette pratique est très utile lorsque les dimensions du nouveau tableau ne sont pas connues dès le début, ou bien sont déterminées pendant l’exécution. Il est également possible qu’une étape spécifique du traitement de données nécessite que l’entrée adopte une forme particulière.

C’est là que le remodelage de tableaux entre en jeu.

Considérez par exemple le cas suivant : nous avons un vecteur, c’est-à-dire un tableau unidimensionnel de 6 éléments, et nous souhaitons le transformer en tableaux de dimensions 2 × 3, 3 × 2, 6 × 1, etc.

▶️ Pour reproduire les exemples de ce tutoriel, vous devez avoir installé Python et NumPy. Si ce n’est pas encore fait, consultez notre guide d’installation de NumPy.

Vous pouvez maintenant importer NumPy en utilisant l’alias np avec la commande : import numpy as np.

Passons à l’étude de la syntaxe dans la section suivante.

Syntaxe de la fonction reshape() de NumPy

Voici la syntaxe pour utiliser la fonction reshape() de NumPy :

np.reshape(arr, newshape, order="C"|'F'|'A')
  • arr représente n’importe quel objet de tableau NumPy valide, c’est-à-dire le tableau à remodeler.
  • newshape définit la structure du nouveau tableau. Il peut s’agir d’un entier ou d’un tuple.
  • Si newshape est un entier, le tableau renvoyé sera unidimensionnel.
  • order indique la manière dont vous souhaitez lire les éléments du tableau à remodeler.
  • La valeur par défaut est ‘C’, ce qui signifie que les éléments du tableau d’origine seront lus selon l’ordre d’indexation de type C (en commençant par 0).
  • ‘F’ correspond à une indexation de type Fortran (en commençant par 1). Et ‘A’ lit les éléments en suivant l’ordre C ou Fortran en fonction de la disposition en mémoire du tableau arr.

Alors, que renvoie np.reshape() ?

Elle renvoie une vue remodelée du tableau original si possible. Sinon, elle crée une copie du tableau.

Nous avons mentionné que reshape() essaierait de renvoyer une vue chaque fois que possible. Commençons par analyser les différences entre une vue et une copie.

Vue ou copie de tableaux NumPy

Comme son nom l’indique, une copie est une réplique du tableau original. Toute modification apportée à la copie n’affectera pas le tableau de départ.

En revanche, une vue est simplement une référence au tableau original remodelé. Cela signifie que toute modification apportée à la vue affectera également le tableau original, et inversement.

Utiliser reshape() pour transformer un tableau 1D en tableaux 2D

#1. Commençons par créer un exemple de tableau en utilisant np.arange().

Nous allons créer un tableau de 12 nombres, de 1 à 12, nommé arr1. Puisque la fonction NumPy arange() exclut le point final par défaut, nous définissons la valeur de fin sur 13.

Utilisons maintenant la syntaxe que nous avons vue plus haut et transformons arr1, un tableau de 12 éléments, en un tableau 2D de forme (4,3). Nommons ce nouveau tableau arr2, qui aura 4 lignes et 3 colonnes.

import numpy as np

arr1 = np.arange(1,13)
print("Tableau original, avant transformation:n")
print(arr1)

# Transformation du tableau
arr2 = np.reshape(arr1,(4,3))
print("nTableau transformé:")
print(arr2)

Observons les tableaux d’origine et transformés.

Tableau original, avant transformation:

[ 1  2  3  4  5  6  7  8  9 10 11 12]

Tableau transformé:
[[ 1  2  3]
 [ 4  5  6]
 [ 7  8  9]
 [10 11 12]]

Plutôt que de transmettre le tableau comme argument à np.reshape(), vous pouvez également utiliser la méthode .reshape() directement sur le tableau initial.

Si vous exécutez dir(arr1), vous obtiendrez la liste de toutes les méthodes et attributs disponibles pour l’objet tableau arr1.

dir(arr1)

# Sortie
[
...
...
'reshape'
...
..
]

Dans le code précédent, vous pouvez constater que .reshape() est une méthode que l’on peut utiliser sur le tableau NumPy arr1.

▶️ Il est donc possible d’utiliser la syntaxe simplifiée suivante pour remodeler les tableaux NumPy.

arr.reshape(d0,d1,...,dn)

# où:

# d0, d1,..,dn sont les dimensions du tableau transformé

# d0 * d1 * ...* dn = N, le nombre d'éléments dans arr

Pour la suite de ce tutoriel, nous allons utiliser cette syntaxe dans nos exemples.

#2. Essayons maintenant de transformer notre vecteur de 12 éléments en un tableau 12 x 1.

import numpy as np

arr1 = np.arange(1,13)
print("Tableau original, avant transformation:n")
print(arr1)

# Transformation du tableau
arr3 = arr1.reshape(12,1)
print("nTableau transformé:")
print(arr3)

La sortie ci-dessous montre que le tableau a été transformé correctement.

Tableau original, avant transformation:

[ 1  2  3  4  5  6  7  8  9 10 11 12]

Tableau transformé:
[[ 1]
 [ 2]
 [ 3]
 [ 4]
 [ 5]
 [ 6]
 [ 7]
 [ 8]
 [ 9]
 [10]
 [11]
 [12]]

❔ Comment vérifier si nous avons obtenu une copie ou une vue ?

Pour cela, vous pouvez utiliser l’attribut base sur le tableau renvoyé.

  • Si le tableau est une copie, l’attribut base sera None.
  • Si le tableau est une vue, l’attribut base sera le tableau original.

Vérifions cela rapidement.

arr3.base
# Sortie
array([ 1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12])

Comme vous pouvez le constater, l’attribut base de arr3 renvoie le tableau original. Cela signifie que nous avons reçu une vue du tableau de départ.

#3. Essayons de transformer le vecteur en un autre tableau 2 x 6 valide.

import numpy as np

arr1 = np.arange(1,13)
print("Tableau original, avant transformation:n")
print(arr1)

# Transformation du tableau
arr4 = arr1.reshape(2,6)
print("nTableau transformé:")
print(arr4)

Voici le résultat :

Tableau original, avant transformation:

[ 1  2  3  4  5  6  7  8  9 10 11 12]

Tableau transformé:
[[ 1  2  3  4  5  6]
 [ 7  8  9 10 11 12]]

Dans la section suivante, nous allons transformer arr1 en un tableau 3D.

Utiliser reshape() pour transformer un tableau 1D en tableaux 3D

Pour transformer arr1 en tableau 3D, nous définissons les dimensions souhaitées à (1, 4, 3).

import numpy as np

arr1 = np.arange(1,13)
print("Tableau original, avant transformation:n")
print(arr1)

# Transformation du tableau
arr3D = arr1.reshape(1,4,3)
print("nTableau transformé:")
print(arr3D)

Nous avons maintenant créé un tableau 3D avec les 12 mêmes éléments que le tableau de départ arr1.

Tableau original, avant transformation:

[ 1  2  3  4  5  6  7  8  9 10 11 12]

Tableau transformé:
[[[ 1  2  3]
  [ 4  5  6]
  [ 7  8  9]
  [10 11 12]]]

Comment corriger les erreurs de valeur lors de la transformation

Comme indiqué dans la syntaxe, la transformation n’est valide que si le produit des dimensions est égal au nombre d’éléments dans le tableau.

import numpy as np

arr1 = np.arange(1,13)
print("Tableau original, avant transformation:n")
print(arr1)

# Transformation du tableau
arr2D = arr1.reshape(4,4)
print("nTableau transformé:")
print(arr2D)

Dans cet exemple, on essaie de transformer un tableau de 12 éléments en un tableau 4 × 4, qui contient 16 éléments. L’interpréteur renvoie une erreur de valeur, comme indiqué ci-dessous.

Tableau original, avant transformation:

[ 1  2  3  4  5  6  7  8  9 10 11 12]
-----------------------------------------------------------
ValueError
Traceback (most recent call last)
<ipython-input-11-63552bcc8c37> in <module>()
      6

      7 # Transformation du tableau
----> 8 arr2 = arr1.reshape(4,4)
      9 print("nTableau transformé:")
     10 print(arr2)

ValueError: cannot reshape array of size 12 into shape (4,4)

Pour éviter ce type d’erreur, vous pouvez utiliser la valeur -1 afin de déduire automatiquement la forme d’une dimension, en fonction du nombre total d’éléments.

Par exemple, si vous connaissez n – 1 dimensions à l’avance, vous pouvez utiliser -1 pour déduire la n-ième dimension dans le tableau transformé.

Si vous avez un tableau de 24 éléments et que vous souhaitez le transformer en tableau 3D, en supposant 3 lignes et 4 colonnes, vous pouvez utiliser la valeur -1 pour la troisième dimension.

import numpy as np

arr1 = np.arange(1,25)
print("Tableau original, avant transformation:n")
print(arr1)

# Transformation du tableau
arr_res = arr1.reshape(4,3,-1)
print("nTableau transformé:")
print(arr_res)
print(f"Forme de arr_res:{arr_res.shape}")

En examinant la forme du tableau, on peut constater que le tableau transformé a une forme de 2 le long de la troisième dimension.

Tableau original, avant transformation:

[ 1  2  3  4  5  6  7  8  9 10 11 12
13 14 15 16 17 18 19 20 21 22 23 24]

Tableau transformé:
[[[ 1  2]
  [ 3  4]
  [ 5  6]]

 [[ 7  8]
  [ 9 10]
  [11 12]]

 [[13 14]
  [15 16]
  [17 18]]

 [[19 20]
  [21 22]
  [23 24]]]
Forme de arr_res:(4, 3, 2)

Cette méthode est très pratique pour aplatir un tableau, comme nous allons le voir dans la section suivante.

Utiliser reshape() pour aplatir un tableau

Dans certaines situations, il est nécessaire de revenir d’un tableau à N dimensions vers un tableau aplati, par exemple pour transformer une image en un vecteur de pixels.

Voici un exemple simple en suivant les étapes suivantes :

  • Générer un tableau d’images en niveaux de gris 3 x 3, img_arr, avec des pixels compris entre 0 et 255.
  • Aplatir ce tableau img_arr et afficher le tableau aplati, flat_arr.
  • Afficher également les formes de img_arr et flat_arr pour vérification.
img_arr = np.random.randint(0, 255, (3,3))
print(img_arr)
print(f"Forme de img_arr: {img_arr.shape}")
flat_arr = img_arr.reshape(-1)
print(flat_arr)
print(f"Forme de flat_arr: {flat_arr.shape}")

Voici le résultat.

[[195 145  77]
 [ 63 193 223]
 [215  43  36]]
Forme de img_arr: (3, 3)

[195 145  77  63 193 223 215  43  36]
Forme de flat_arr: (9,)

Comme vous pouvez le voir, flat_arr est un vecteur 1D avec les 9 valeurs de pixel.

Résumé👩‍🏫

Récapitulons rapidement ce que nous avons appris :

  • Utilisez np.reshape(arr, newshape) pour transformer arr selon la forme indiquée dans newshape. newshape est un tuple précisant les dimensions du tableau transformé.
  • Vous pouvez également utiliser arr.reshape(d0, d1, …, dn) pour transformer arr afin qu’il ait la forme d0 x d1 x … x dn.
  • Vérifiez que d0 * d1 * …* dn = N, le nombre d’éléments du tableau de départ, pour éviter les erreurs de valeur lors de la transformation.
  • Utilisez la valeur -1 pour une seule dimension maximum dans la nouvelle forme si vous souhaitez que la dimension soit déduite automatiquement.
  • Enfin, vous pouvez utiliser arr.reshape(-1) pour aplatir le tableau.

Maintenant que vous maîtrisez la fonction reshape() de NumPy, découvrez comment fonctionne la fonction linspace() de NumPy.

Si vous le souhaitez, vous pouvez essayer les exemples de code dans un notebook Jupyter. Si vous cherchez d’autres environnements de développement, consultez notre guide sur les alternatives à Jupyter.