relaxon
relaxon

Reputation: 141

Python split array into intersecting subarrays

I would like to split an array into equally long intersecting subarrays (last element of previous array coincides with first element of the next array and with periodic boundary conditions).

E.g.

myarray = np.arange(18)

output:

splitarray = [[0,1,2,3,4],[4,5,6,7,8],[8,9,10,11,12],[12,13,14,15,16],[16,17,0,1,2]]

(the 3 last elements of the last subarray correspond to the first 3 elements of the initial array!)

What is the most efficient way to implement this in Python?

Upvotes: 1

Views: 294

Answers (2)

Mad Physicist
Mad Physicist

Reputation: 114440

The pure-numpy equivalent of ski.util.view_as_windows is np.lib.stride_tricks.as_strided:

arr = np.arange(18)
w = 5

if arr.size == 1:
    h = 1
    x = 4
else:
    h = np.ceil((arr.size - 1) / (w - 1)).astype(int)
    x = (1 - arr.size) % (w - 1)

view = np.lib.stride_tricks.as_strided(np.r_[arr, arr[:x]], shape=(h, w), strides=((w - 1) * arr.strides[0], arr.strides[0]))

The result is:

>>> view
array([[ 0,  1,  2,  3,  4],
       [ 4,  5,  6,  7,  8],
       [ 8,  9, 10, 11, 12],
       [12, 13, 14, 15, 16],
       [16, 17,  0,  1,  2]])

The overlapping elements are actually referring to the same memory, so use this view very very carefully.

Upvotes: 3

yatu
yatu

Reputation: 88276

You could use skimage's view_as_windows to take overlapping views of the input array, and concatenate the first w-1 items accordingly for the last window:

from skimage.util import view_as_windows

def view_strided_with_roll(a, w):
    a = np.r_[a, a[:w-1]]
    return view_as_windows(a, window_shape=w, step=w-1)

myarray = np.arange(18) 
view_strided_with_roll(myarray, 5)
array([[ 0,  1,  2,  3,  4],
       [ 4,  5,  6,  7,  8],
       [ 8,  9, 10, 11, 12],
       [12, 13, 14, 15, 16],
       [16, 17,  0,  1,  2]])

Upvotes: 2

Related Questions