Cómo aplanar solo algunas dimensiones de una matriz numpy

128

¿Hay una manera rápida de "sub-aplanar" o aplanar solo algunas de las primeras dimensiones en una matriz numpy?

Por ejemplo, dada una gran variedad de dimensiones (50,100,25), las dimensiones resultantes serían(5000,25)

Curioso
fuente
1
Esto podría ayudar a stackoverflow.com/questions/13990465/3d-numpy-array-to-2d
Ankur Ankan
Necesita un curso de actualización sobre el corte de matriz ndarray numpy. También conocido como indexación de matriz multidimensional, consulte: docs.scipy.org/doc/numpy-1.13.0/reference/arrays.indexing.html Array corte su ndarray usando corchetes, y use el delimitador de coma para separar cuánto de cada dimensión que quieras. Se verá algo así (no exactamente) así: your_array[50:100, 7, :]que aplana el objeto 3d a 2d, usando solo el corte número 7 para la 2da dimensión.
Eric Leschinski

Respuestas:

129

Echa un vistazo a 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)
Alejandro
fuente
81

Una ligera generalización a la respuesta de Alexander: np.reshape puede tomar -1 como argumento, lo que significa "tamaño de matriz total dividido por el producto de todas las demás dimensiones enumeradas":

Por ejemplo, para aplanar todo menos la última dimensión:

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

Una ligera generalización a la respuesta de Peter: puede especificar un rango sobre la forma de la matriz original si desea ir más allá de las matrices tridimensionales.

por ejemplo, para aplanar todas las dos dimensiones excepto las últimas :

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

EDITAR: Una ligera generalización a mi respuesta anterior: por supuesto, también puede especificar un rango al comienzo de la remodelación:

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
fuente
2
Ya han pasado más de dos años ... ¡Necesitamos otra ligera generalización! ;)
Lith
1

Un enfoque alternativo es usar numpy.resize()como en:

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
fuente