2D array of all 1D cyclic shifts

Suppose a is 1d numppy.array with n elements:

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

I would like to generate 2d (n X n) numpy.array containing in the line i the ith cyclic shift a :

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

preferably without loops. How can this be done effectively?

(The np.roll function seems to be related, but apparently only takes up the shift scalar.)

+5
source share
2 answers

you are actually building a circulant matrix. Just use the scipy circulant function . Be careful because you have to go in the first vertical column, not the first row:

 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]] 

For reference, circulant matrices have very nice properties .

+9
source

If you want to do this manually, just use np.tile :

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

Replicate it to the tile, but again than necessary to get the desired "shift"

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

Then change it so that it is a 2D matrix with the form (a, a+1)

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

Well, that was just a debugging step to see what was going on. But if you see this, you know that you just need to delete the last column:

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

And then you have the desired result.


This can also be generalized to allow (almost) arbitrary shifts:

 shift = 3 a = np.array([...]) b = np.tile(a, a.size+shift) res = b.reshape(a.size, a.size+shift)[:,:-shift] 
+2
source

Source: https://habr.com/ru/post/1244841/


All Articles