Skip to content

NumPy : Comment utiliser reshape() et la signification de -1

Pour convertir la forme d’un ndarray de tableau NumPy, utilisez la méthode reshape() de ndarray ou la fonction numpy.reshape().

Cet article décrit le contenu suivant.

  • Comment utiliser la méthode ndarray.reshape()
  • Comment utiliser la fonction numpy.reshape()
  • Ordre de transformation :order
  • La signification de -1 dans reshape()
  • reshape() renvoie la vue

Si vous souhaitez vérifier la forme ou le nombre de dimensions de ndarray, consultez l’article suivant.

Vous pouvez utiliser reshape() pour convertir en n’importe quelle forme, mais il peut y avoir des alternatives disponibles pour plus de commodité dans certaines conversions de forme.

De plus, en fonctionnement entre tableaux NumPy (ndarray), chaque forme est automatiquement convertie pour être la même par diffusion.

Comment utiliser la méthode ndarray.reshape()

Prenez le tableau NumPy unidimensionnel suivant ndarray comme exemple.

import numpy as np

a = np.arange(24)

print(a)
# [ 0  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19 20 21 22 23]

print(a.shape)
# (24,)

print(a.ndim)
# 1

Spécifiez la forme sous forme de liste ou de tuple dans le premier argument de la méthode reshape() de numpy.ndarray.

a_4_6 = a.reshape([4, 6])

print(a_4_6)
# [[ 0  1  2  3  4  5]
#  [ 6  7  8  9 10 11]
#  [12 13 14 15 16 17]
#  [18 19 20 21 22 23]]

print(a_4_6.shape)
# (4, 6)

print(a_4_6.ndim)
# 2
a_2_3_4 = a.reshape([2, 3, 4])

print(a_2_3_4)
# [[[ 0  1  2  3]
#   [ 4  5  6  7]
#   [ 8  9 10 11]]
# 
#  [[12 13 14 15]
#   [16 17 18 19]
#   [20 21 22 23]]]

print(a_2_3_4.shape)
# (2, 3, 4)

print(a_2_3_4.ndim)
# 3

Si la forme ne correspond pas au nombre d’éléments du tableau d’origine, ValueError se produit.

# a_5_6 = a.reshape([5, 6])
# ValueError: cannot reshape array of size 24 into shape (5,6)

Vous pouvez spécifier tour à tour chaque valeur de dimension, et non une liste ou un tuple.

print(a.reshape(4, 6))
# [[ 0  1  2  3  4  5]
#  [ 6  7  8  9 10 11]
#  [12 13 14 15 16 17]
#  [18 19 20 21 22 23]]

print(a.reshape(2, 3, 4))
# [[[ 0  1  2  3]
#   [ 4  5  6  7]
#   [ 8  9 10 11]]
# 
#  [[12 13 14 15]
#   [16 17 18 19]
#   [20 21 22 23]]]

Comment utiliser la fonction numpy.reshape()

Dans la fonction numpy.reshape(), spécifiez le numpy.ndarray d’origine comme premier argument et la forme du deuxième argument comme liste ou tuple. Si la forme ne correspond pas au nombre d’éléments du tableau d’origine, ValueError se produit.

print(np.reshape(a, [4, 6]))
# [[ 0  1  2  3  4  5]
#  [ 6  7  8  9 10 11]
#  [12 13 14 15 16 17]
#  [18 19 20 21 22 23]]

print(np.reshape(a, [2, 3, 4]))
# [[[ 0  1  2  3]
#   [ 4  5  6  7]
#   [ 8  9 10 11]]
# 
#  [[12 13 14 15]
#   [16 17 18 19]
#   [20 21 22 23]]]

# print(np.reshape(a, [5, 6]))
# ValueError: cannot reshape array of size 24 into shape (5,6)

Le deuxième argument de la fonction numpy.reshape() doit être une liste ou un tuple. Si vous spécifiez la valeur de chaque dimension tour à tour, comme la méthode reshape() de numpy.ndarray, ValueError est déclenché.

print(a.reshape(4, 6))
# [[ 0  1  2  3  4  5]
#  [ 6  7  8  9 10 11]
#  [12 13 14 15 16 17]
#  [18 19 20 21 22 23]]

# print(np.reshape(a, 4, 6))
# ValueError: cannot reshape array of size 24 into shape (4,)

Ordre de transformation :order

L’ordre de conversion peut être spécifié avec l’argument order. order= »C » (par défaut) signifie un ordre d’index de type C, order= »F » signifie un ordre d’index de type Fortran.

Les résultats sont différents comme suit.

print(a.reshape([4, 6], order='C'))
# [[ 0  1  2  3  4  5]
#  [ 6  7  8  9 10 11]
#  [12 13 14 15 16 17]
#  [18 19 20 21 22 23]]

print(a.reshape([4, 6], order='F'))
# [[ 0  4  8 12 16 20]
#  [ 1  5  9 13 17 21]
#  [ 2  6 10 14 18 22]
#  [ 3  7 11 15 19 23]]

print(a.reshape([2, 3, 4], order='C'))
# [[[ 0  1  2  3]
#   [ 4  5  6  7]
#   [ 8  9 10 11]]
# 
#  [[12 13 14 15]
#   [16 17 18 19]
#   [20 21 22 23]]]

print(a.reshape([2, 3, 4], order='F'))
# [[[ 0  6 12 18]
#   [ 2  8 14 20]
#   [ 4 10 16 22]]
# 
#  [[ 1  7 13 19]
#   [ 3  9 15 21]
#   [ 5 11 17 23]]]

Idem pour la fonction numpy.reshape() :

print(np.reshape(a, [4, 6], order='F'))
# [[ 0  4  8 12 16 20]
#  [ 1  5  9 13 17 21]
#  [ 2  6 10 14 18 22]
#  [ 3  7 11 15 19 23]]

La méthode reshape() de numpy.ndarray vous permet de spécifier tour à tour la forme de chaque dimension comme décrit ci-dessus, donc si vous spécifiez l’ordre des arguments, vous devez utiliser le mot-clé.

Dans la fonction numpy.reshape(), le troisième argument est toujours order, donc le mot-clé peut être omis.

# print(a.reshape([4, 6], 'F'))
# TypeError: 'list' object cannot be interpreted as an integer

print(np.reshape(a, [4, 6], 'F'))
# [[ 0  4  8 12 16 20]
#  [ 1  5  9 13 17 21]
#  [ 2  6 10 14 18 22]
#  [ 3  7 11 15 19 23]]

La signification de -1 dans reshape()

Vous pouvez utiliser -1 pour spécifier la forme dans reshape().

Prenez la méthode reshape() de numpy.ndarray comme exemple, mais il en va de même pour la fonction numpy.reshape().

La longueur de la dimension définie sur -1 est automatiquement déterminée en déduisant des valeurs spécifiées des autres dimensions. Ceci est utile lors de la conversion d’une grande forme de tableau.

print(a.reshape([4, -1]))
# [[ 0  1  2  3  4  5]
#  [ 6  7  8  9 10 11]
#  [12 13 14 15 16 17]
#  [18 19 20 21 22 23]]

print(a.reshape([2, -1, 4]))
# [[[ 0  1  2  3]
#   [ 4  5  6  7]
#   [ 8  9 10 11]]
# 
#  [[12 13 14 15]
#   [16 17 18 19]
#   [20 21 22 23]]]

Vous pouvez utiliser -1 pour une seule dimension. S’il est utilisé pour plusieurs dimensions, ValueError se produit.

# print(a.reshape([2, -1, -1]))
# ValueError: can only specify one unknown dimension

De plus, si aucune valeur ne satisfait la condition, ValueError est déclenché.

# print(a.reshape([2, -1, 5]))
# ValueError: cannot reshape array of size 24 into shape (2,newaxis,5)

reshape() renvoie la vue

Notez que la méthode reshape() de numpy.ndarray et la fonction numpy.reshape() renvoient une vue au lieu d’une copie chaque fois que possible. Comme c’est « autant que possible », une copie peut être renvoyée à la place d’une vue en fonction de la disposition de la mémoire.

Consultez l’article suivant pour les vues et les copies dans NumPy.

L’exemple suivant utilise la méthode reshape() de numpy.ndarray, mais il en va de même pour la fonction numpy.reshape().

reshape() renvoie une vue et partage la mémoire avec le numpy.ndarray d’origine.

a = np.arange(8)
print(a)
# [0 1 2 3 4 5 6 7]

a_2_4 = a.reshape([2, 4])
print(a_2_4)
# [[0 1 2 3]
#  [4 5 6 7]]

print(np.shares_memory(a, a_2_4))
# True

La modification de l’objet d’origine modifie l’objet de vue renvoyé par reshape() comme suit :

a[0] = 100
print(a)
# [100   1   2   3   4   5   6   7]

print(a_2_4)
# [[100   1   2   3]
#  [  4   5   6   7]]

Il en va de même pour le cas inverse. La modification de l’objet de vue renvoyé par reshape() modifie l’objet d’origine.

a_2_4[0, 0] = 0
print(a_2_4)
# [[0 1 2 3]
#  [4 5 6 7]]

print(a)
# [0 1 2 3 4 5 6 7]

Si vous voulez obtenir une copie, utilisez la méthode copy(). Dans ce cas, la modification de chaque objet n’affecte pas l’autre objet.

a_2_4_copy = a.reshape([2, 4]).copy()
print(a_2_4_copy)
# [[0 1 2 3]
#  [4 5 6 7]]

print(np.shares_memory(a, a_2_4_copy))
# False

a[0] = 100
print(a)
# [100   1   2   3   4   5   6   7]

print(a_2_4_copy)
# [[0 1 2 3]
#  [4 5 6 7]]

a_2_4_copy[0, 0] = 200
print(a_2_4_copy)
# [[200   1   2   3]
#  [  4   5   6   7]]

print(a)
# [100   1   2   3   4   5   6   7]

Voici un exemple où reshape() renvoie une copie au lieu d’une vue :

Si la foulée en mémoire n’est pas constante suite à la transformation d’une tranche spécifiée par pas, une copie est renvoyée.

a = np.arange(6).reshape(2, 3)
print(a)
# [[0 1 2]
#  [3 4 5]]

a_step = a[:, ::2]
print(a_step)
# [[0 2]
#  [3 5]]

print(a_step.reshape(-1))
# [0 2 3 5]

print(np.shares_memory(a_step, a_step.reshape(-1)))
# False

Pour une tranche spécifiée par étape, si la foulée est constante, une vue est renvoyée.

a = np.arange(8).reshape(2, 4)
print(a)
# [[0 1 2 3]
#  [4 5 6 7]]

a_step = a[:, ::2]
print(a_step)
# [[0 2]
#  [4 6]]

print(a_step.reshape(-1))
# [0 2 4 6]

print(np.shares_memory(a_step, a_step.reshape(-1)))
# True