2015-08-23 1 views

Odpowiedz

34

prawdopodobnie najczystszym sposobem jest użycie np.repeat:

a = np.array([[1, 2], [1, 2]]) 
print(a.shape) 
# (2, 2) 

# indexing with np.newaxis inserts a new 3rd dimension, which we then repeat the 
# array along, (you can achieve the same effect by indexing with None, see below) 
b = np.repeat(a[:, :, np.newaxis], 3, axis=2) 

print(b.shape) 
# (2, 2, 3) 

print(b[:, :, 0]) 
# [[1 2] 
# [1 2]] 

print(b[:, :, 1]) 
# [[1 2] 
# [1 2]] 

print(b[:, :, 2]) 
# [[1 2] 
# [1 2]] 

Mimo, że często można uniknąć powtarzania swoich tablic łącznie za pomocą broadcasting. Na przykład, powiedzmy, że chciałem dodać (3,) wektor:

c = np.array([1, 2, 3]) 

do a. Mogłem skopiować trzy razy zawartość trzeciego wymiaru, a następnie skopiować zawartość c dwa razy w pierwszym i drugim wymiarze, tak aby obie moje macierze były (2, 2, 3), a następnie obliczyć ich sumę. Jednakże, jest to o wiele prostsze i szybsze, aby to zrobić:

d = a[..., None] + c[None, None, :] 

Tutaj a[..., None] ma kształt (2, 2, 1) i c[None, None, :] ma kształt (1, 1, 3) *. Kiedy obliczyć sumę, wynik staje się „nadawać” wzdłuż wymiarów wielkości 1, dając mi wyniku kształtu (2, 2, 3):

print(d.shape) 
# (2, 2, 3) 

print(d[..., 0]) # a + c[0] 
# [[2 3] 
# [2 3]] 

print(d[..., 1]) # a + c[1] 
# [[3 4] 
# [3 4]] 

print(d[..., 2]) # a + c[2] 
# [[4 5] 
# [4 5]] 

Broadcasting jest bardzo potężna technika, ponieważ unika się dodatkowego narzutu związanego w tworzeniu powtórzone kopie twoich tablic wejściowych w pamięci.


* Chociaż wliczone ich jasności, None indeksy język c nie są rzeczywiście konieczne - można również zrobić a[..., None] + c, czyli nadawać (2, 2, 1) tablicę przeciwko (3,) tablicy. Wynika to z tego, że jeśli jedna z macierzy ma mniejszą liczbę wymiarów niż druga, to tylko wymiary z obu macierzy muszą być zgodne. Aby podać bardziej skomplikowany przykład:

a = np.ones((6, 1, 4, 3, 1)) # 6 x 1 x 4 x 3 x 1 
b = np.ones((5, 1, 3, 2))  #  5 x 1 x 3 x 2 
result = a + b    # 6 x 5 x 4 x 3 x 2 
+0

celu sprawdzenia, czy rzeczywiście daje prawo wynik, można również wydrukować 'b [:,:, 0] ',' b [:,:, 1] 'i' b [:,:, 2] '. Każdy trzeci wycinek wymiaru jest kopią oryginalnej tablicy 2D. To nie jest tak oczywiste, patrząc na "print (b)". – ely

+0

To jest świetna odpowiedź !! Dziękuję Ci! – drg

11

Innym sposobem jest użycie numpy.dstack. Przypuśćmy, że chcesz powtórzyć matrycy anum_repeats razy:

import numpy as np 
b = np.dstack([a]*num_repeats) 

Sztuką jest owinąć matrycę a do listy pojedynczego elementu, a następnie za pomocą operatora * powielać elementów na tej liście num_repeats razy.

Na przykład, jeżeli:

a = np.array([[1, 2], [1, 2]]) 
num_repeats = 5 

Powtarza tablicę [1 2; 1 2] 5 razy w trzecim wymiarze.W celu zweryfikowania (w ipython)

In [110]: import numpy as np 

In [111]: num_repeats = 5 

In [112]: a = np.array([[1, 2], [1, 2]]) 

In [113]: b = np.dstack([a]*num_repeats) 

In [114]: b[:,:,0] 
Out[114]: 
array([[1, 2], 
     [1, 2]]) 

In [115]: b[:,:,1] 
Out[115]: 
array([[1, 2], 
     [1, 2]]) 

In [116]: b[:,:,2] 
Out[116]: 
array([[1, 2], 
     [1, 2]]) 

In [117]: b[:,:,3] 
Out[117]: 
array([[1, 2], 
     [1, 2]]) 

In [118]: b[:,:,4] 
Out[118]: 
array([[1, 2], 
     [1, 2]]) 

In [119]: b.shape 
Out[119]: (2, 2, 5) 

Na koniec widać, że kształt matrycy 2 x 2, 5 plastry w trzecim wymiarze.

+0

Jak to się porównuje do 'reshape'? Szybciej? daje taką samą strukturę? Jest zdecydowanie schludniejszy. –

+0

@AnderBiguri Nigdy nie testowałem ... Umieściłem to tutaj głównie dla kompletności. To będzie interesujące dla czasu i zobaczenia różnic. – rayryeng

+1

Po prostu zrobiłem img = np.dstack ([arr] * 3) i działałem dobrze! Dziękuję –

2
A=np.array([[1,2],[3,4]]) 
B=np.asarray([A]*N) 

Edit @ Mr.F, aby zachować porządek Wymiary:

B=B.T 
+0

Powoduje to dla mnie tablicę N x 2 x 2, np. 'B.shape' wypisuje' (N, 2, 2) 'dla dowolnej wartości' N'. Jeśli transponujesz 'B' z' B.T', to pasuje do oczekiwanego wyniku. – ely

+0

@ Mr.F - Masz rację. To będzie transmitowane wzdłuż pierwszego wymiaru, a więc robienie 'B [0], B [1], ...' da ci właściwy kawałek, który będę argumentował i mówię, że jest łatwiejszy do wpisania niż użycie 'B [:,:, 0], B [:,:, 1] ', itp. – rayryeng

+0

Może być łatwiejszy do wpisania, ale na przykład, jeśli robisz to z danymi obrazu, będzie to w dużej mierze niepoprawne, ponieważ prawie wszystkie algorytmy będą oczekiwać, że konwencje algebry liniowej będą stosowane w przypadku fragmentów 2D kanałów pikseli. Trudno wyobrazić sobie aplikacje, w których zaczynasz od tablicy 2D, traktując wiersze i kolumny z pewną konwencją, a następnie chcesz, aby wiele kopii tej samej rzeczy rozszerzyło się do nowej osi, ale nagle chcesz, aby pierwsza oś zmieniła być nową osią ... – ely

1

Oto przykład nadawanie że robi dokładnie to, co było wymagane.

a = np.array([[1, 2], [1, 2]]) 
a=a[:,:,None] 
b=np.array([1]*5)[None,None,:] 

Następnie b*a jest pożądany rezultat i (b*a)[:,:,0] produkuje array([[1, 2],[1, 2]]), która jest oryginalna a, podobnie jak (b*a)[:,:,1] itp