
Vous pouvez aplatir un tableau NumPy ndarray avec la fonction numpy.label() ou les méthodes ravel() et flatten() de numpy.ndarray.
Cet article décrit le contenu suivant.
- Aplatir un tableau NumPy avec numpy.ravel()
- Aplatir un tableau NumPy avec ndarray.ravel()
- Aplatir un tableau NumPy avec ndarray.flatten()
- Aplatir un tableau NumPy avec reshape(-1)
- Différence entre ravel() et flatten()
- Comparaison de vitesse entre ravel() et flatten()
- Le paramètre de commande
- Pour les tableaux multidimensionnels
Consultez l’article suivant sur l’aplatissement des listes multidimensionnelles (type de liste intégré de Python).
Aplatir un tableau NumPy avec numpy.ravel()
Vous pouvez aplatir un tableau NumPy avec la fonction numpy.label(). Un numpy.ndarray aplati est renvoyé.
import numpy as np
a = np.arange(12).reshape(3, 4)
print(a)
# [[ 0 1 2 3]
# [ 4 5 6 7]
# [ 8 9 10 11]]
print(np.ravel(a))
# [ 0 1 2 3 4 5 6 7 8 9 10 11]
print(type(np.ravel(a)))
# <class 'numpy.ndarray'>
Vous pouvez spécifier un soi-disant objet de type tableau, tel que la liste intégrée de Python. Dans ce cas, également, numpy.ndarray est renvoyé.
print(np.ravel([[0, 1, 2, 3], [4, 5, 6, 7], [8, 9, 10, 11]]))
# [ 0 1 2 3 4 5 6 7 8 9 10 11]
print(type(np.ravel([[0, 1, 2, 3], [4, 5, 6, 7], [8, 9, 10, 11]])))
# <class 'numpy.ndarray'>
Notez que si le nombre d’éléments dans la liste interne est différent, numpy.ndarray avec la liste en tant qu’éléments est renvoyé.
print(np.ravel([[0, 1, 2, 3], [4, 5, 6, 7], [8, 9]]))
# [list([0, 1, 2, 3]) list([4, 5, 6, 7]) list([8, 9])]
print(type(np.ravel([[0, 1, 2, 3], [4, 5, 6, 7], [8, 9]])))
# <class 'numpy.ndarray'>
Si vous souhaitez aplatir une telle liste, consultez l’article suivant.
Aplatir un tableau NumPy avec ndarray.ravel()
ravel() est également fourni comme méthode de numpy.ndarray.
print(a.ravel())
# [ 0 1 2 3 4 5 6 7 8 9 10 11]
Aplatir un tableau NumPy avec ndarray.flatten()
flatten() est également fourni comme méthode de numpy.ndarray.
print(a.flatten())
# [ 0 1 2 3 4 5 6 7 8 9 10 11]
ravel() renvoie une vue si possible, mais flatten() renvoie toujours une copie. flatten() est plus lent que ravel() car il doit allouer de la mémoire. Voir ci-dessous pour plus de détails.
Notez qu’à partir de la version 1.17, flatten() est fourni uniquement en tant que méthode de numpy.ndarray, et non en tant que fonction comme numpy.flatten() (np.flatten()).
Aplatir un tableau NumPy avec reshape(-1)
Vous pouvez également utiliser reshape() pour convertir la forme d’un tableau NumPy en une dimension. Si vous utilisez -1, la taille est calculée automatiquement, vous pouvez donc aplatir un tableau NumPy avec reshape(-1).
reshape() est fourni en tant que méthode de numpy.ndarray.
print(a.reshape(-1))
# [ 0 1 2 3 4 5 6 7 8 9 10 11]
La fonction numpy.reshape() est également fournie. numpy.reshape() peut gérer des objets de type tableau tels que des listes ainsi que numpy.reval().
print(np.reshape(a, -1))
# [ 0 1 2 3 4 5 6 7 8 9 10 11]
print(np.reshape([[0, 1, 2, 3], [4, 5, 6, 7], [8, 9, 10, 11]], -1))
# [ 0 1 2 3 4 5 6 7 8 9 10 11]
print(np.reshape([[0, 1, 2, 3], [4, 5, 6, 7], [8, 9]], -1))
# [list([0, 1, 2, 3]) list([4, 5, 6, 7]) list([8, 9])]
Différence entre ravel() et flatten()
ravel() et reshape() renvoient une vue si possible, tandis que flatten() renvoie toujours une copie.
Consultez l’article suivant pour plus d’informations sur les vues et les copies de numpy.ndarray.
print(np.shares_memory(a, a.ravel()))
# True
print(np.shares_memory(a, np.ravel(a)))
# True
print(np.shares_memory(a, a.flatten()))
# False
print(np.shares_memory(a, a.reshape(-1)))
# True
print(np.shares_memory(a, np.reshape(a, -1)))
# True
Dans le cas d’une vue, il partage la mémoire avec le numpy.ndarray d’origine, donc si vous modifiez la valeur de l’un, la valeur de l’autre changera également.
a_ravel = a.ravel()
print(a_ravel)
# [ 0 1 2 3 4 5 6 7 8 9 10 11]
a_ravel[0] = 100
print(a_ravel)
# [100 1 2 3 4 5 6 7 8 9 10 11]
print(a)
# [[100 1 2 3]
# [ 4 5 6 7]
# [ 8 9 10 11]]
Dans le cas d’une copie, de la mémoire est allouée pour chacun, ils sont donc traités séparément les uns des autres.
ravel() et reshape() renvoient des vues si possible, mais dans certains cas, elles renvoient des copies.
Par exemple, ravel() et reshape() renvoient également une copie si la tranche avec un pas spécifié est aplatie et que la foulée en mémoire n’est pas constante.
a = np.arange(12).reshape(3, 4)
print(a)
# [[ 0 1 2 3]
# [ 4 5 6 7]
# [ 8 9 10 11]]
print(a[:, ::3])
# [[ 0 3]
# [ 4 7]
# [ 8 11]]
print(np.shares_memory(a[:, ::3], np.ravel(a[:, ::3])))
# False
print(np.shares_memory(a[:, ::3], np.reshape(a[:, ::3], -1)))
# False
Dans certains cas, ravel() et reshape() donnent des résultats différents. Si la foulée est constante même pour une tranche avec un pas, reshape() renvoie une vue, mais ravel() renvoie une copie.
print(a[:, ::2])
# [[ 0 2]
# [ 4 6]
# [ 8 10]]
print(np.shares_memory(a[:, ::2], np.ravel(a[:, ::2])))
# False
print(np.shares_memory(a[:, ::2], np.reshape(a[:, ::2], -1)))
# True
Comme le disent les notes dans la documentation officielle, reshape(-1) est préférable à ravel() si vous voulez qu’une vue soit souhaitée dans le plus de cas possible.
Lorsqu’une vue est souhaitée dans autant de cas que possible, arr.reshape(-1) peut être préférable.
numpy.ravel — Manuel NumPy v1.17
Comparaison de vitesse entre ravel() et flatten().
flatten(), qui renvoie une copie, est plus lent que ravel() car il doit allouer de la nouvelle mémoire.
Le code suivant est mesuré à l’aide de la commande magique %%timeit sur Jupyter Notebook. Notez que cela ne fonctionne pas sur le script Python.
a = np.arange(12).reshape(3, 4)
print(a)
# [[ 0 1 2 3]
# [ 4 5 6 7]
# [ 8 9 10 11]]
%%timeit
a.ravel()
# 242 ns ± 2.78 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
%%timeit
a.flatten()
# 725 ns ± 45.2 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
%%timeit
a.reshape(-1)
# 851 ns ± 13.5 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
Pour numpy.ndarray aussi petit que l’exemple ci-dessus, vous n’avez pas à vous en soucier, mais si la taille est grande, flatten() prendra beaucoup plus de temps. Bien sûr, flatten() utilise plus de mémoire que ravel().
Si cela ne vous dérange pas d’utiliser des vues au lieu de copies, il est préférable d’utiliser ravel().
a_large = np.arange(1000000).reshape(100, 100, 100)
%%timeit
a_large.ravel()
# 242 ns ± 3.6 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
%%timeit
a_large.flatten()
# 2.03 ms ± 8.63 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
%%timeit
a_large.reshape(-1)
# 899 ns ± 52 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
Notez que ravel() alloue également de la nouvelle mémoire lorsqu’il renvoie une copie, donc sa vitesse et son utilisation de la mémoire sont les mêmes que flatten().
Le paramètre de commande
Le paramètre order peut être spécifié pour ravel(), flatten() et reshape().
Le paramètre par défaut est order= »C », qui s’aplatit avec une ligne majeure de type C comme dans les exemples précédents, mais si vous définissez order= »F », il s’aplatit avec une colonne majeure de type Fortran.
a = np.arange(12).reshape(3, 4)
print(a)
# [[ 0 1 2 3]
# [ 4 5 6 7]
# [ 8 9 10 11]]
print(a.ravel())
# [ 0 1 2 3 4 5 6 7 8 9 10 11]
print(a.ravel('F'))
# [ 0 4 8 1 5 9 2 6 10 3 7 11]
print(np.ravel(a, 'F'))
# [ 0 4 8 1 5 9 2 6 10 3 7 11]
print(a.flatten('F'))
# [ 0 4 8 1 5 9 2 6 10 3 7 11]
print(a.reshape(-1, order='F'))
# [ 0 4 8 1 5 9 2 6 10 3 7 11]
print(np.reshape(a, -1, order='F'))
# [ 0 4 8 1 5 9 2 6 10 3 7 11]
order peut être ‘C’, ‘F’, ‘A’ pour reshape(), et ‘C’, ‘F’, ‘A’, ‘K’ pour ravel() et flatten().
Voir la documentation officielle pour plus de détails sur chacun.
Notez que les options ‘C’ et ‘F’ ne tiennent pas compte de l’agencement de la mémoire du tableau sous-jacent et se réfèrent uniquement à l’ordre d’indexation des axes. ‘A’ signifie lire les éléments dans l’ordre d’index de type Fortran si a est Fortran contigu en mémoire, dans l’ordre de type C sinon. ‘K’ signifie lire les éléments dans l’ordre où ils apparaissent en mémoire, sauf pour inverser les données lorsque les foulées sont négatives. Par défaut, l’ordre d’index ‘C’ est utilisé.
numpy.ravel — Manuel NumPy v1.17
Les différences par ordre sont présentées ci-dessous, ainsi que des informations sur numpy.ndarray, qui peuvent être vérifiées avec np.info().
Par exemple, si fortran est True, les résultats de ‘A’ et ‘F’ sont égaux, et si fortran est False, les résultats de ‘A’ et ‘C’ sont égaux.
np.info(a)
# class: ndarray
# shape: (3, 4)
# strides: (32, 8)
# itemsize: 8
# aligned: True
# contiguous: True
# fortran: False
# data pointer: 0x7fe081640f90
# byteorder: little
# byteswap: False
# type: int64
print(a.ravel('C'))
# [ 0 1 2 3 4 5 6 7 8 9 10 11]
print(a.ravel('F'))
# [ 0 4 8 1 5 9 2 6 10 3 7 11]
print(a.ravel('A'))
# [ 0 1 2 3 4 5 6 7 8 9 10 11]
print(a.ravel('K'))
# [ 0 1 2 3 4 5 6 7 8 9 10 11]
Lorsqu’il est transposé avec l’attribut T :
print(a.T)
# [[ 0 4 8]
# [ 1 5 9]
# [ 2 6 10]
# [ 3 7 11]]
np.info(a.T)
# class: ndarray
# shape: (4, 3)
# strides: (8, 32)
# itemsize: 8
# aligned: True
# contiguous: False
# fortran: True
# data pointer: 0x7fe081640f90
# byteorder: little
# byteswap: False
# type: int64
print(a.T.ravel('C'))
# [ 0 4 8 1 5 9 2 6 10 3 7 11]
print(a.T.ravel('F'))
# [ 0 1 2 3 4 5 6 7 8 9 10 11]
print(a.T.ravel('A'))
# [ 0 1 2 3 4 5 6 7 8 9 10 11]
print(a.T.ravel('K'))
# [ 0 1 2 3 4 5 6 7 8 9 10 11]
Tranche avec pas négatif :
print(a.T[::-1])
# [[ 3 7 11]
# [ 2 6 10]
# [ 1 5 9]
# [ 0 4 8]]
np.info(a.T[::-1])
# class: ndarray
# shape: (4, 3)
# strides: (-8, 32)
# itemsize: 8
# aligned: True
# contiguous: False
# fortran: False
# data pointer: 0x7fe081640fa8
# byteorder: little
# byteswap: False
# type: int64
print(a.T[::-1].ravel('C'))
# [ 3 7 11 2 6 10 1 5 9 0 4 8]
print(a.T[::-1].ravel('F'))
# [ 3 2 1 0 7 6 5 4 11 10 9 8]
print(a.T[::-1].ravel('A'))
# [ 3 7 11 2 6 10 1 5 9 0 4 8]
print(a.T[::-1].ravel('K'))
# [ 3 2 1 0 7 6 5 4 11 10 9 8]
Pour les tableaux multidimensionnels
Jusqu’à présent, les exemples concernent des tableaux bidimensionnels, mais les tableaux multidimensionnels de trois dimensions ou plus peuvent être aplatis de la même manière.
a_3d = np.arange(24).reshape(2, 3, 4)
print(a_3d)
# [[[ 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_3d.ravel())
# [ 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_3d.ravel('F'))
# [ 0 12 4 16 8 20 1 13 5 17 9 21 2 14 6 18 10 22 3 15 7 19 11 23]
Notez que l’effet d’ordre est compliqué dans le cas de tableaux multidimensionnels, comme le montre l’exemple ci-dessus.