Como nivelar apenas algumas dimensões de uma matriz numpy

127

Existe uma maneira rápida de "subplainar" ou nivelar apenas algumas das primeiras dimensões de uma matriz numpy?

Por exemplo, dada uma matriz numpy de dimensões (50,100,25), as dimensões resultantes seriam(5000,25)

Curioso
fonte
Você precisa de um curso de reciclagem de fatias de matriz numpy ndarray. Também conhecida como indexação de matriz multidimensional, consulte: docs.scipy.org/doc/numpy-1.13.0/reference/arrays.indexing.html A matriz divide seu ndarray usando colchetes e use o delimitador de vírgula para separar quanto de cada dimensão que você deseja. Será algo como (não exatamente) o seguinte: your_array[50:100, 7, :]que nivela o objeto 3d para 2d, usando apenas a fatia número 7 para a 2ª dimensão.
Eric Leschinski 31/08/19

Respostas:

129

Dê uma olhada no 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)
Alexander
fonte
81

Uma leve generalização na resposta de Alexander - np.reshape pode assumir -1 como argumento, significando "tamanho total da matriz dividido pelo produto de todas as outras dimensões listadas":

por exemplo, para nivelar tudo, exceto a última dimensão:

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

Uma leve generalização na resposta de Peter - você pode especificar um intervalo acima da forma da matriz original se quiser ir além das matrizes tridimensionais.

por exemplo, para nivelar todas, exceto as duas últimas dimensões:

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

EDIT: Uma ligeira generalização para a minha resposta anterior - é claro, você também pode especificar um intervalo no início da remodelação:

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
fonte
2
Já faz mais de dois anos ... Precisamos de outra ligeira generalização! ;)
Lith
1

Uma abordagem alternativa é usar numpy.resize()como em:

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
fonte