2016-03-10 13 views
5

Załóżmy a pewne 1d numppy.array z n elementów:2D tablicę wszystkich przesunięć cyklicznych 1D tablicy

a = np.array([a_0, a_1, ..., a_n_minus_1]) 

ja, aby wygenerować 2d (nX n) numpy.array zawierający z rzędu i The i p cykliczne przesunięcie a:

np.array([[a_0, a_1, ..., a_n_minus_1], [a_n_minus_1, a_0, a_1, ...], ...]]) 

najlepiej bez pętli. Jak można to zrobić skutecznie?

(Funkcja np.roll wydaje podobne, ale najwyraźniej trwa tylko skalarne shift.)

+0

Trick robi to skutecznie jest użycie przekątnych. Na przykład główna przekątna będzie pierwszym elementem, itd. –

+0

@JoeKington Way cool, thanks! IIUC, masz zamiar wykorzystać fakt, że cykliczne przesunięcie może być uważane za transformację liniową, tak? –

+0

@JoeKington Właściwie brzmi to bardzo dobrze, ale nie mogę tego rozgryźć - generowanie macierzy wykonujących różne przekształcenia liniowe byłoby bardzo kosztowne, nie? –

Odpowiedz

9

jesteś rzeczywiście buduje circulant matrycy. Po prostu użyj scipy circulant function. Bądź ostrożny, ponieważ trzeba przejść w pierwszej kolumnie pionowej, nie pierwszy wiersz:

from scipy.linalg import circulant 
circulant([1,4,3,2] 
> array([[1, 2, 3, 4], 
     [4, 1, 2, 3], 
     [3, 4, 1, 2], 
     [2, 3, 4, 1]] 

odsyłającym circulant matryce mają bardzo ładne properties.

2

Jeśli chcesz to zrobić ręcznie, wystarczy użyć np.tile:

import numpy as np 
a = np.array([1,2,3]) 

replikować go z płytki ale jeszcze raz niż rzeczywiście potrzebne, aby uzyskać poszukiwany „shift”

b = np.tile(a, a.size+1) 
# [1 2 3 1 2 3 1 2 3 1 2 3] 

Wtedy zmienią to jest matryca 2D o kształcie (a, a+1)

b.reshape(a.size, a.size+1) 
#[[1 2 3 1] 
# [2 3 1 2] 
# [3 1 2 3]] 

OK, t kapelusz był tylko krokiem do debugowania, aby zobaczyć, co się dzieje. Ale jeśli widzisz, wiesz, że musisz usunąć ostatnią kolumnę:

b.reshape(a.size, a.size+1)[:,:-1] 

A potem masz swój pożądany wynik.


To również może być uogólniony, aby umożliwić (prawie) arbitralne zmiany:

shift = 3 
a = np.array([...]) 
b = np.tile(a, a.size+shift) 
res = b.reshape(a.size, a.size+shift)[:,:-shift] 
Powiązane problemy