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ètre | Type | Description |
|---|---|---|
array | ndarray | Le tableau à remodeler (uniquement pour la forme fonction np.reshape()) |
newshape | int ou tuple d'ints | La 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 dimensionreshape() vs resize() : Différences clés
Les deux fonctions changent la forme des tableaux, mais elles se comportent très différemment.
| Caractéristique | reshape() | resize() |
|---|---|---|
| Retourne | Nouveau tableau (vue ou copie) | Modifie le tableau en place (méthode) ou retourne un nouveau tableau (fonction) |
| La taille doit correspondre | Oui -- le total des éléments doit être identique | Non -- remplit avec des zéros ou tronque |
| Tableau original | Inchangé | Modifié (lors de l'utilisation de ndarray.resize()) |
| Sécurité | Lance une erreur en cas de discordance de taille | Remplit ou tronque silencieusement |
| Usage courant | Réorganiser les dimensions | Changer 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]]| Order | Nom | Remplissage | Cas d'utilisation |
|---|---|---|---|
'C' | Style C / Par lignes | Ligne par ligne (le dernier indice change le plus vite) | Disposition mémoire par défaut Python/C/C++ |
'F' | Style Fortran / Par colonnes | Colonne par colonne (le premier indice change le plus vite) | Données MATLAB, Fortran, R |
'A' | Automatique | Utilise F si le tableau est contigu en Fortran, sinon C | Pré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 copieErreurs 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 :
- 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]]- 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]]- 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.newaxisounp.squeezeselon 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
-1pour 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. Utilisezorder='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.