Comment aplatir uniquement certaines dimensions d'un tableau numpy

128

Existe-t-il un moyen rapide de "sous-aplatir" ou d'aplatir uniquement certaines des premières dimensions d'un tableau numpy?

Par exemple, étant donné un tableau numpy de dimensions (50,100,25), les dimensions résultantes seraient(5000,25)

Curieuse
la source
Vous avez besoin d'un cours de recyclage sur le découpage des tableaux numpy ndarray. Également connue sous le nom d'indexation de tableau multidimensionnel, voir: docs.scipy.org/doc/numpy-1.13.0/reference/arrays.indexing.html Array tranche votre ndarray à l'aide de crochets et utilisez le séparateur virgule pour séparer la quantité de chaque dimension que vous voulez. Cela ressemblera à quelque chose comme (pas exactement) ceci: your_array[50:100, 7, :]qui aplatit l'objet 3D en 2D, en utilisant uniquement la tranche numéro 7 pour la 2ème dimension.
Eric Leschinski

Réponses:

129

Jetez un œil à numpy.reshape .

>>> arr = numpy.zeros((50,100,25))
>>> arr.shape
# (50, 100, 25)

>>> new_arr = arr.reshape(5000,25)
>>> new_arr.shape   
# (5000, 25)

# One shape dimension can be -1. 
# In this case, the value is inferred from 
# the length of the array and remaining dimensions.
>>> another_arr = arr.reshape(-1, arr.shape[-1])
>>> another_arr.shape
# (5000, 25)
Alexandre
la source
81

Une légère généralisation à la réponse d'Alexandre - np.reshape peut prendre -1 comme argument, ce qui signifie "taille totale du tableau divisée par le produit de toutes les autres dimensions répertoriées":

par exemple pour aplatir tout sauf la dernière dimension:

>>> arr = numpy.zeros((50,100,25))
>>> new_arr = arr.reshape(-1, arr.shape[-1])
>>> new_arr.shape
# (5000, 25)
Peter
la source
33

Une légère généralisation à la réponse de Peter - vous pouvez spécifier une plage sur la forme du tableau d'origine si vous voulez aller au-delà des tableaux en trois dimensions.

par exemple pour aplatir toutes les dimensions sauf les deux dernières :

arr = numpy.zeros((3, 4, 5, 6))
new_arr = arr.reshape(-1, *arr.shape[-2:])
new_arr.shape
# (12, 5, 6)

EDIT: Une légère généralisation à ma réponse précédente - vous pouvez, bien sûr, également spécifier une plage au début de la refonte:

arr = numpy.zeros((3, 4, 5, 6, 7, 8))
new_arr = arr.reshape(*arr.shape[:2], -1, *arr.shape[-2:])
new_arr.shape
# (3, 4, 30, 7, 8)
KeithWM
la source
2
Cela fait déjà plus de deux ans ... Il faut encore une petite généralisation! ;)
Lith
1

Une approche alternative consiste à utiliser numpy.resize()comme dans:

In [37]: shp = (50,100,25)
In [38]: arr = np.random.random_sample(shp)
In [45]: resized_arr = np.resize(arr, (np.prod(shp[:2]), shp[-1]))
In [46]: resized_arr.shape
Out[46]: (5000, 25)

# sanity check with other solutions
In [47]: resized = np.reshape(arr, (-1, shp[-1]))
In [48]: np.allclose(resized_arr, resized)
Out[48]: True
kmario23
la source