2015-06-11 5 views
5

w Matlab, można wykonać następujące czynności:Łatwy sposób na zwinięcie końcowych wymiarów tablicy numpy?

X = randn(25,25,25); 
size(X(:,:)) 

ans = 
    25 625 

I często znajduję się chcąc szybko zwijać końcowe wymiary tablicy, i nie wiem, jak to zrobić w numpy.

wiem, że mogę to zrobić:

In [22]: x = np.random.randn(25,25,25) 
In [23]: x = x.reshape(x.shape[:-2] + (-1,)) 
In [24]: x.shape 
Out[24]: (25, 625) 

ale x.reshape(x.shape[:-2] + (-1,)) jest dużo mniej zwięzły (i wymaga więcej informacji o x) niż po prostu robi x(:,:).

Mam oczywiście próbowaliśmy analogiczną numpy indeksowanie, ale to nie działa zgodnie z oczekiwaniami:

In [25]: x = np.random.randn(25,25,25) 
In [26]: x[:,:].shape 
Out[26]: (25, 25, 25) 

żadnych wskazówek, w jaki sposób zwijać końcowe wymiary tablicy w zwięzły sposób?

Edycja: zauważ, że szukam wynikowej tablicy, a nie tylko jej kształtu. Używam tylko size() i x.shape w powyższych przykładach, aby wskazać, jaka jest tablica.

+0

Na marginesie Twój przykład jest niepoprawny ... 'x.shape [: - 2]' dałoby pustą krotkę. (Dodanie do niego '-1' oznacza, że ​​tablica zostanie" spłaszczona "w tablicy o długości 15625). Domyślam się, że chodziło o' x.shape [0] '? –

+0

@JoeKington: It * is * correct (try it). 'x.shape [: - 2]' zwraca 'x.shape' do (ale nie włączając) elementu od drugiego do ostatniego. Tak więc dla tablicy 3D 'x' zwraca tylko pierwszy element' x.shape'. Użyłem '[: -2]' zamiast '[0]', ponieważ szukam ogólnego rozwiązania, które działa dla wszystkich macierzy ND, gdzie N> 2. – EelkeSpaak

+0

@ElkeSpaak - Racja. Nie myślałem jasno. –

Odpowiedz

3

Co ma się stać z 4d lub wyższym?

octave:7> x=randn(25,25,25,25); 
octave:8> size(x(:,:)) 
ans = 
     25 15625 

Twój (:,:) redukuje go do 2 wymiarów, łącząc ostatnie. Ostatni wymiar to miejsce, w którym MATLAB automatycznie dodaje i zwija wymiary.

In [605]: x=np.ones((25,25,25,25)) 

In [606]: x.reshape(x.shape[0],-1).shape # like Joe's 
Out[606]: (25, 15625) 

In [607]: x.reshape(x.shape[:-2]+(-1,)).shape 
Out[607]: (25, 25, 625) 

Twój reshape przykład robi coś innego od MATLAB, to po prostu upadnie ostatni 2. Zwijanie go w dół do 2 wymiarach jak MATLAB jest prostsze wyrażenie.

MATLAB jest zwięzły, ponieważ Twoje potrzeby są zgodne z jego założeniami. Równowartość numpy nie jest tak zwięzły, ale daje większą kontrolę

Na przykład, aby utrzymać ostatni wymiar lub połączyć Rozmiary 2 od 2:

In [608]: x.reshape(-1,x.shape[-1]).shape 
Out[608]: (15625, 25) 
In [610]: x.reshape(-1,np.prod(x.shape[-2:])).shape 
Out[610]: (625, 625) 

Co to jest równoważne MATLAB?

octave:24> size(reshape(x,[],size(x)(2:end))) 
ans = 
15625  25 
octave:31> size(reshape(x,[],prod(size(x)(3:end)))) 
1

Można użyć np.hstack:

>>> np.hstack(x).shape 
(25, 625) 

np.hstack ake sekwencji tablic i ułóż je w poziomie, aby wykonać jedną tablicę.

+1

To interesujące użycie 'np.hstack'! Jednak nie daje tego samego wyniku co 'x.reshape (x.shape [: - 2] + (-1,))', dlatego należy go używać ostrożnie. Myśląc o tym nieco dalej, wierzę, że 'np.hstack' traktuje * pierwszy * wymiar tablicy jako wymiar iterowalny, a więc zwraca to samo co' np.hstack (x [0 ,: ,:], x [1,:,:], ...) '. Potrzebuję funkcjonalności, która pozostawia nietknięty pierwszy wymiar (tj. Wszystkie dane poprzednio w x [0,:,:] są teraz w x [0 ,:]), tak jak w przypadku wersji Matlaba. – EelkeSpaak

+0

Czy chcesz nowej tablicy lub po prostu chcesz jej kształt? – Kasramvd

+0

Jestem po zawartości samej tablicy, kształt jest po prostu dla ilustracji. Przygotowałem oryginalne pytanie, aby było to bardziej jasne. – EelkeSpaak

1

Może się okazać, że bardziej zwięzłe jest modyfikowanie atrybutu shape bezpośrednio. Na przykład:

import numpy as np 

x = np.random.randn(25, 25, 25) 
x.shape = x.shape[0], -1 

print x.shape 
print x 

To jest funkcjonalnym odpowiednikiem reshape (w sensie porządkowania danych, etc). Oczywiście nadal wymaga to tych samych informacji o kształcie x, ale jest to bardziej zwięzły sposób obsługi zmiany kształtu.

+1

Ma dodatkową "korzyść", która, jeśli przekształcenie nie może być wykonane bez kopii, spowoduje błąd, więc często używam go jako formy potwierdzenia, że ​​mój kod wydajnie korzysta z pamięci. – Jaime