Skip to content Skip to sidebar Skip to footer

Accessing Chunks At Once In A Numpy Array

Provided a numpy array: arr = np.array([0,1,2,3,4,5,6,7,8,9,10,11,12]) I wonder how access chosen size chunks with chosen separation, both concatenated and in slices: E.g.: obtain

Solution 1:

Approach #1

Here's one with masking -

defslice_grps(a, chunk, sep):
    N = chunk + sep
    return a[np.arange(len(a))%N < chunk]

Sample run -

In [223]: arr
Out[223]: array([ 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12])

In [224]: slice_grps(arr, chunk=3, sep=2)
Out[224]: array([ 0,  1,  2,  5,  6,  7, 10, 11, 12])

Approach #2

If the input array is such that the last chunk would have enough runway, we could , we could leverage np.lib.stride_tricks.as_strided, inspired by this post to select m elements off each block of n elements -

# https://stackoverflow.com/a/51640641/ @Divakardef skipped_view(a, m, n):
    s = a.strides[0]
    strided = np.lib.stride_tricks.as_strided
    shp = ((a.size+n-1)//n,n)returnstrided(a,shape=shp,strides=(n*s,s), writeable=False)[:,:m]

out = skipped_view(arr,chunk,chunk+sep)

Note that the output would be a view into the input array and as such no extra memory overhead and virtually free!

Sample run to make things clear -

In [255]: arr
Out[255]: array([ 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12])

In [256]: chunk = 3

In [257]: sep = 2

In [258]: skipped_view(arr,chunk,chunk+sep)
Out[258]: 
array([[ 0,  1,  2],
       [ 5,  6,  7],
       [10, 11, 12]])

# Let's prove that the output is a view indeed
In [259]: np.shares_memory(arr, skipped_view(arr,chunk,chunk+sep))
Out[259]: True

Solution 2:

How about a reshape and slice?

In [444]: arr = np.array([0,1,2,3,4,5,6,7,8,9,10,11,12])
In [445]: arr.reshape(-1,5)
...
ValueError: cannot reshape array of size 13 into shape (5)

Ah a problem - your array isn't big enough for this reshape - so we have to pad it:

In [446]: np.concatenate((arr,np.zeros(2,int))).reshape(-1,5)
Out[446]: 
array([[ 0,  1,  2,  3,  4],
       [ 5,  6,  7,  8,  9],
       [10, 11, 12,  0,  0]])
In [447]: np.concatenate((arr,np.zeros(2,int))).reshape(-1,5)[:,:-2]
Out[447]: 
array([[ 0,  1,  2],
       [ 5,  6,  7],
       [10, 11, 12]])

as_strided can get a way with this by including bytes outside the databuffer. Usually that's seen as a bug, though here it can be an asset - provided you really do throw that garbage away.

Or throwing away the last incomplete line:

In [452]: arr[:-3].reshape(-1,5)[:,:3]
Out[452]: 
array([[0, 1, 2],
       [5, 6, 7]])

Post a Comment for "Accessing Chunks At Once In A Numpy Array"