Come appiattire solo alcune dimensioni di un array numpy


128

C'è un modo rapido per "sub-appiattire" o appiattire solo alcune delle prime dimensioni in un array numpy?

Ad esempio, data una matrice numpy di dimensioni (50,100,25), le dimensioni risultanti sarebbero(5000,25)



Hai bisogno di un corso di aggiornamento sull'affettatura dell'array numpy ndarray. Conosciuta anche come indicizzazione di array multidimensionale, vedi: docs.scipy.org/doc/numpy-1.13.0/reference/arrays.indexing.html Array affetta il tuo ndarray usando parentesi quadre e usa il delimitatore virgola per separarne la quantità dimensione che desideri. Assomiglierà (non esattamente) a questo: your_array[50:100, 7, :]che appiattisce l'oggetto 3d in 2d, usando solo lo slice numero 7 per la seconda dimensione.
Eric Leschinski

Risposte:


129

Dai un'occhiata 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)

81

Una leggera generalizzazione alla risposta di Alexander: np.reshape può prendere -1 come argomento, che significa "dimensione totale dell'array divisa per il prodotto di tutte le altre dimensioni elencate":

ad es. per appiattire tutte le dimensioni tranne l'ultima:

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

33

Una leggera generalizzazione alla risposta di Peter: puoi specificare un intervallo sulla forma dell'array originale se vuoi andare oltre gli array tridimensionali.

ad esempio per appiattire tutte le dimensioni tranne le ultime due :

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

EDIT: Una leggera generalizzazione alla mia risposta precedente: puoi, ovviamente, anche specificare un intervallo all'inizio del rimodellamento:

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)

2
Sono già passati più di due anni ... Abbiamo bisogno di un'altra leggera generalizzazione! ;)
Lith

1

Un approccio alternativo consiste nell'utilizzare numpy.resize()come in:

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
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.