Skip to content
Thèmes
NumPy
NumPy Reshape: How to Change Array Shapes in Python

NumPy Reshape : Comment changer la forme des tableaux en Python

Updated on

Vous avez une liste plate de 10 000 valeurs de pixels et un réseau neuronal qui attend une matrice d'image 100x100. Ou peut-être que scikit-learn lance une erreur parce que votre tableau de caractéristiques est unidimensionnel alors qu'il devrait être un vecteur colonne. Ce ne sont pas des cas marginaux -- ce sont des obstacles quotidiens pour quiconque travaille avec des données numériques en Python. La fonction qui les résout est numpy.reshape(), et la comprendre correctement fait gagner des heures de débogage.

📚

Que fait numpy reshape ?

numpy.reshape() change la forme d'un tableau sans modifier ses données. Elle prend les mêmes éléments et les réorganise dans un nouvel ensemble de dimensions. Un tableau 1D de 12 éléments peut devenir une matrice 3x4, une matrice 2x6, une matrice 4x3, ou même un tableau tridimensionnel 2x2x3. La seule règle est que le nombre total d'éléments doit rester identique.

import numpy as np
 
a = np.array([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12])
print(a.shape)
# (12,)
 
b = a.reshape(3, 4)
print(b)
# [[ 1  2  3  4]
#  [ 5  6  7  8]
#  [ 9 10 11 12]]
 
print(b.shape)
# (3, 4)

Le tableau original a existe toujours avec sa forme originale. Le tableau remodelé b est une nouvelle vue des mêmes données (plus de détails sur les vues vs les copies plus tard).

Syntaxe de base et paramètres

Il existe deux façons de remodeler un tableau dans NumPy :

# Méthode 1 : En tant que fonction
np.reshape(array, newshape, order='C')
 
# Méthode 2 : En tant que méthode du tableau
array.reshape(newshape, order='C')
ParamètreTypeDescription
arrayndarrayLe tableau à remodeler (uniquement pour la forme fonction np.reshape())
newshapeint ou tuple d'intsLa forme cible. Une dimension peut être -1, calculée automatiquement.
order'C', 'F' ou 'A'Ordre de lecture/écriture des éléments. 'C' = par lignes (défaut), 'F' = par colonnes, 'A' = ordre Fortran si le tableau est contigu en Fortran, ordre C sinon.

Les deux formes produisent des résultats identiques. La forme méthode (array.reshape()) est plus courante car elle se lit plus naturellement dans le code.

Remodeler des tableaux de 1D en 2D

C'est l'opération de reshape la plus fréquente. Vous partez d'un tableau plat et avez besoin d'une matrice.

import numpy as np
 
# Tableau 1D avec 8 éléments
data = np.array([10, 20, 30, 40, 50, 60, 70, 80])
 
# Remodeler en 2 lignes, 4 colonnes
matrix_2x4 = data.reshape(2, 4)
print(matrix_2x4)
# [[10 20 30 40]
#  [50 60 70 80]]
 
# Remodeler en 4 lignes, 2 colonnes
matrix_4x2 = data.reshape(4, 2)
print(matrix_4x2)
# [[10 20]
#  [30 40]
#  [50 60]
#  [70 80]]
 
# Remodeler en vecteur colonne (8 lignes, 1 colonne)
column_vector = data.reshape(8, 1)
print(column_vector)
# [[10]
#  [20]
#  [30]
#  [40]
#  [50]
#  [60]
#  [70]
#  [80]]
 
print(column_vector.shape)
# (8, 1)

Le remodelage en vecteur colonne (n, 1) est particulièrement important. De nombreuses fonctions scikit-learn exigent une entrée 2D même pour une seule caractéristique. Si vous passez un tableau 1D, vous obtenez l'erreur Expected 2D array, got 1D array instead. La solution est .reshape(-1, 1).

Remodeler de 2D en 3D (Pour le Machine Learning et le Deep Learning)

Les frameworks de deep learning comme TensorFlow et PyTorch exigent souvent des tenseurs d'entrée 3D ou 4D. Par exemple, un lot d'images en niveaux de gris nécessite la forme (batch_size, height, width), et un lot d'images en couleur nécessite (batch_size, height, width, channels).

import numpy as np
 
# Simuler 4 images en niveaux de gris 3x3 stockées comme lignes dans un tableau 2D
images_2d = np.arange(36).reshape(4, 9)
print(images_2d.shape)
# (4, 9)
 
# Remodeler en (lot, hauteur, largeur)
images_3d = images_2d.reshape(4, 3, 3)
print(images_3d.shape)
# (4, 3, 3)
 
print(images_3d[0])
# [[0 1 2]
#  [3 4 5]
#  [6 7 8]]

Pour des images en couleur avec 3 canaux (RGB) :

import numpy as np
 
# 2 images en couleur, chacune 4x4 avec 3 canaux, stockées à plat
flat_data = np.arange(96)  # 2 * 4 * 4 * 3 = 96
 
images = flat_data.reshape(2, 4, 4, 3)
print(images.shape)
# (2, 4, 4, 3)

L'astuce du -1 : Calculer automatiquement une dimension

Lorsque vous définissez une dimension à -1, NumPy la calcule automatiquement en fonction du nombre total d'éléments et des autres dimensions que vous avez spécifiées. C'est l'une des fonctionnalités les plus utiles de reshape.

import numpy as np
 
arr = np.arange(12)
 
# "Donne-moi 3 lignes, calcule les colonnes"
print(arr.reshape(3, -1))
# [[ 0  1  2  3]
#  [ 4  5  6  7]
#  [ 8  9 10 11]]
# Forme : (3, 4) -- NumPy a calculé 4 colonnes
 
# "Donne-moi 2 colonnes, calcule les lignes"
print(arr.reshape(-1, 2))
# [[ 0  1]
#  [ 2  3]
#  [ 4  5]
#  [ 6  7]
#  [ 8  9]
#  [10 11]]
# Forme : (6, 2) -- NumPy a calculé 6 lignes
 
# Aplatir en 1D
print(arr.reshape(-1))
# [ 0  1  2  3  4  5  6  7  8  9 10 11]
# Forme : (12,)
 
# Vecteur colonne
print(arr.reshape(-1, 1).shape)
# (12, 1)

Vous ne pouvez utiliser -1 que pour une seule dimension. L'utiliser pour deux dimensions ou plus génère une erreur car le calcul devient ambigu.

import numpy as np
 
arr = np.arange(12)
 
# Ceci ÉCHOUE :
# arr.reshape(-1, -1)
# ValueError: can only specify one unknown dimension

reshape() vs resize() : Différences clés

Les deux fonctions changent la forme des tableaux, mais elles se comportent très différemment.

Caractéristiquereshape()resize()
RetourneNouveau tableau (vue ou copie)Modifie le tableau en place (méthode) ou retourne un nouveau tableau (fonction)
La taille doit correspondreOui -- le total des éléments doit être identiqueNon -- remplit avec des zéros ou tronque
Tableau originalInchangéModifié (lors de l'utilisation de ndarray.resize())
SécuritéLance une erreur en cas de discordance de tailleRemplit ou tronque silencieusement
Usage courantRéorganiser les dimensionsChanger la taille du tableau
import numpy as np
 
arr = np.array([1, 2, 3, 4, 5, 6])
 
# reshape : doit garder le même total d'éléments
reshaped = arr.reshape(2, 3)
print(reshaped)
# [[1 2 3]
#  [4 5 6]]
 
# np.resize (forme fonction) : remplit par répétition si la nouvelle taille est plus grande
resized = np.resize(arr, (3, 3))
print(resized)
# [[1 2 3]
#  [4 5 6]
#  [1 2 3]]   <-- répète depuis le début
 
# np.resize : tronque si la nouvelle taille est plus petite
resized_small = np.resize(arr, (2, 2))
print(resized_small)
# [[1 2]
#  [3 4]]

Utilisez reshape() lorsque vous voulez réorganiser les dimensions sans changer les données. Utilisez resize() uniquement lorsque vous avez véritablement besoin de changer le nombre d'éléments.

Le paramètre order : C vs F vs A

Le paramètre order contrôle la façon dont les éléments sont lus du tableau original et placés dans la nouvelle forme. Cela compte lorsque vous travaillez avec des données provenant de différents langages de programmation ou formats de stockage.

import numpy as np
 
arr = np.array([1, 2, 3, 4, 5, 6])
 
# Ordre C (par lignes) : remplit ligne par ligne -- c'est le défaut
c_order = arr.reshape(2, 3, order='C')
print("Ordre C :")
print(c_order)
# [[1 2 3]
#  [4 5 6]]
 
# Ordre F (par colonnes) : remplit colonne par colonne
f_order = arr.reshape(2, 3, order='F')
print("Ordre F :")
print(f_order)
# [[1 3 5]
#  [2 4 6]]
OrderNomRemplissageCas d'utilisation
'C'Style C / Par lignesLigne par ligne (le dernier indice change le plus vite)Disposition mémoire par défaut Python/C/C++
'F'Style Fortran / Par colonnesColonne par colonne (le premier indice change le plus vite)Données MATLAB, Fortran, R
'A'AutomatiqueUtilise F si le tableau est contigu en Fortran, sinon CPréserver la disposition mémoire existante

La plupart du temps, vous utiliserez l'ordre 'C' par défaut. Vous avez besoin de l'ordre 'F' lorsque vous chargez des données exportées depuis MATLAB ou Fortran, où les matrices sont stockées colonne par colonne.

Vues vs copies : Quand reshape retourne une vue

Un détail critique : reshape() retourne une vue du tableau original chaque fois que c'est possible. Une vue partage la même mémoire sous-jacente. Modifier la vue modifie le tableau original, et vice versa.

import numpy as np
 
original = np.arange(6)
reshaped = original.reshape(2, 3)
 
# Modifier la vue remodelée
reshaped[0, 0] = 999
 
print(original)
# [999   1   2   3   4   5]   <-- l'original a aussi changé !

Si NumPy ne peut pas créer une vue (par exemple, lorsque la disposition mémoire n'est pas compatible avec la nouvelle forme), il retourne une copie à la place. Vous pouvez forcer une copie explicitement :

import numpy as np
 
original = np.arange(6)
reshaped_copy = original.reshape(2, 3).copy()
 
reshaped_copy[0, 0] = 999
print(original)
# [0 1 2 3 4 5]   <-- l'original N'EST PAS affecté

Pour vérifier si un reshape a retourné une vue ou une copie, inspectez l'attribut base :

import numpy as np
 
arr = np.arange(6)
view = arr.reshape(2, 3)
copy = arr.reshape(2, 3).copy()
 
print(view.base is arr)   # True -- c'est une vue
print(copy.base is arr)   # False -- c'est une copie

Erreurs courantes et comment les corriger

Erreur : "cannot reshape array of size X into shape Y"

C'est l'erreur de reshape la plus courante. Elle survient lorsque le nombre total d'éléments ne correspond pas à la forme cible.

import numpy as np
 
arr = np.arange(10)
 
# Ceci ÉCHOUE car 10 != 3 * 4 = 12
# arr.reshape(3, 4)
# ValueError: cannot reshape array of size 10 into shape (3,4)

Solutions :

  1. Vérifiez vos calculs. Assurez-vous que le produit de toutes les dimensions cibles est égal à arr.size.
import numpy as np
 
arr = np.arange(10)
print(arr.size)  # 10
 
# Formes valides pour 10 éléments : (2,5), (5,2), (1,10), (10,1), (10,)
print(arr.reshape(2, 5))
# [[0 1 2 3 4]
#  [5 6 7 8 9]]
  1. Complétez ou tronquez le tableau si vous avez vraiment besoin d'une forme qui ne divise pas uniformément.
import numpy as np
 
arr = np.arange(10)
 
# Compléter à 12 éléments, puis remodeler en (3, 4)
padded = np.pad(arr, (0, 2), constant_values=0)
print(padded.reshape(3, 4))
# [[0 1 2 3]
#  [4 5 6 7]
#  [8 9 0 0]]
  1. Utilisez -1 pour laisser NumPy calculer une dimension pour vous, évitant les erreurs de calcul manuel.
import numpy as np
 
arr = np.arange(10)
print(arr.reshape(-1, 2))
# [[0 1]
#  [2 3]
#  [4 5]
#  [6 7]
#  [8 9]]

Erreur : "Expected 2D array, got 1D array instead"

Cette erreur scikit-learn apparaît lorsque vous passez un tableau de caractéristiques 1D. La solution est simple :

import numpy as np
 
features = np.array([1.5, 2.3, 3.1, 4.7, 5.0])
 
# Convertir en vecteur colonne
features_2d = features.reshape(-1, 1)
print(features_2d.shape)
# (5, 1)

Exemples pratiques

Préparer les données pour Scikit-Learn

scikit-learn attend des matrices de caractéristiques avec la forme (n_samples, n_features). Voici comment remodeler correctement les données pour une régression linéaire simple :

import numpy as np
 
# Caractéristique unique : tailles de maisons en pieds carrés
sizes = np.array([850, 1200, 1500, 1800, 2100, 2400, 2800])
 
# Remodeler en (n_samples, 1) pour sklearn
X = sizes.reshape(-1, 1)
print(X.shape)
# (7, 1)
 
# La variable cible (prix) est déjà 1D, ce que sklearn accepte
y = np.array([150000, 220000, 275000, 320000, 380000, 430000, 510000])
 
# Maintenant X et y sont prêts pour sklearn
# from sklearn.linear_model import LinearRegression
# model = LinearRegression().fit(X, y)

Remodeler des données d'images

Travailler avec des jeux de données d'images nécessite souvent de remodeler entre des vecteurs plats et des dimensions spatiales :

import numpy as np
 
# Simuler le chargement d'une image en niveaux de gris 28x28 comme tableau plat (comme MNIST)
flat_image = np.random.randint(0, 256, size=784)
print(flat_image.shape)
# (784,)
 
# Remodeler en image 2D
image_2d = flat_image.reshape(28, 28)
print(image_2d.shape)
# (28, 28)
 
# Remodeler un lot de 100 images pour l'entrée d'un réseau neuronal
batch_flat = np.random.randint(0, 256, size=(100, 784))
batch_images = batch_flat.reshape(100, 28, 28, 1)  # ajouter la dimension de canal
print(batch_images.shape)
# (100, 28, 28, 1)

Transposer avec reshape (et pourquoi vous ne devriez pas)

Une erreur courante est d'utiliser reshape pour "transposer" une matrice. Reshape réordonne les éléments dans l'ordre mémoire, ce qui n'est pas la même chose que transposer.

import numpy as np
 
matrix = np.array([[1, 2, 3],
                   [4, 5, 6]])
 
# INCORRECT : reshape(3, 2) ne transpose PAS
wrong = matrix.reshape(3, 2)
print("reshape(3,2) :")
print(wrong)
# [[1 2]
#  [3 4]
#  [5 6]]
 
# CORRECT : utilisez .T ou np.transpose()
correct = matrix.T
print("Transposer :")
print(correct)
# [[1 4]
#  [2 5]
#  [3 6]]

Travailler avec NumPy Reshape dans RunCell

Si vous remodelez fréquemment des tableaux et souhaitez un flux de travail plus rapide, RunCell (opens in a new tab) est un agent IA qui fonctionne directement dans les notebooks Jupyter. Il est conçu pour les data scientists qui passent leur journée à écrire du code NumPy, pandas et scikit-learn.

RunCell peut aider avec les opérations de reshape de plusieurs façons :

  • Débogage instantané des formes. Lorsque vous rencontrez une erreur de discordance de forme, RunCell lit le traceback et suggère l'appel reshape correct, y compris les bonnes dimensions et le paramètre order.
  • Génération automatique de code standard. Décrivez ce dont vous avez besoin en langage naturel -- "remodeler ce tableau plat en un lot d'images 32x32 avec 3 canaux" -- et RunCell écrit le code.
  • Explorer les alternatives. RunCell peut vous montrer si vous devez utiliser reshape, np.expand_dims, np.newaxis ou np.squeeze selon votre situation spécifique.

Comme RunCell fonctionne directement dans votre environnement Jupyter, vous gardez le contrôle total de vos données et de votre code tout en recevant des suggestions assistées par IA exactement là où vous en avez besoin.

FAQ

Que fait numpy reshape(-1) ?

L'appel array.reshape(-1) aplatit le tableau en une dimension. Le -1 indique à NumPy de calculer automatiquement le nombre total d'éléments. C'est équivalent à array.ravel() ou array.flatten(), bien que reshape(-1) retourne une vue lorsque c'est possible tandis que flatten() retourne toujours une copie.

Est-ce que numpy reshape modifie le tableau original ?

Non. reshape() retourne un nouvel objet tableau. Cependant, si le tableau retourné est une vue (ce qui est généralement le cas), modifier le tableau remodelé modifiera également l'original car ils partagent la même mémoire. Pour éviter cela, appelez .copy() sur le résultat.

Quelle est la différence entre reshape et flatten ?

reshape() peut convertir un tableau vers n'importe quelle forme compatible. flatten() convertit toujours en un tableau 1D et retourne toujours une copie. ravel() convertit également en 1D mais retourne une vue lorsque c'est possible, similaire à reshape(-1).

Puis-je remodeler un DataFrame pandas avec numpy reshape ?

Pas directement. Vous devez d'abord extraire le tableau NumPy sous-jacent en utilisant df.values ou df.to_numpy(), puis le remodeler. Pour les opérations de remodelage spécifiques aux DataFrame, utilisez les méthodes pandas comme pivot(), melt(), stack() ou unstack().

Comment remodeler un tableau pour ajouter un nouvel axe ?

Vous pouvez utiliser reshape(), mais np.expand_dims() ou np.newaxis est plus propre pour ajouter une seule dimension :

import numpy as np
 
arr = np.array([1, 2, 3])
 
# Avec reshape
print(arr.reshape(1, 3).shape)   # (1, 3)
print(arr.reshape(3, 1).shape)   # (3, 1)
 
# Avec np.newaxis (plus lisible)
print(arr[np.newaxis, :].shape)  # (1, 3)
print(arr[:, np.newaxis].shape)  # (3, 1)

Conclusion

numpy.reshape() est l'une des fonctions les plus fréquemment utilisées dans la bibliothèque NumPy. Elle vous permet de convertir entre des tableaux 1D, 2D, 3D et de dimensions supérieures sans copier les données (dans la plupart des cas). Les points clés à retenir :

  • Le nombre total d'éléments doit rester identique avant et après le remodelage.
  • Utilisez -1 pour une dimension pour laisser NumPy la calculer automatiquement.
  • reshape() retourne généralement une vue, pas une copie. Les modifications de la vue affectent l'original.
  • L'order='C' par défaut remplit les éléments ligne par ligne. Utilisez order='F' pour les données en colonne majeure provenant de MATLAB ou Fortran.
  • Quand scikit-learn se plaint de tableaux 1D, .reshape(-1, 1) est votre solution.

Maîtrisez ces modèles et vous gérerez les discordances de forme en toute confiance, que vous prépariez des données tabulaires pour le machine learning ou que vous remodeliez des tenseurs d'images pour le deep learning.

📚