Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python/Numpy fast way to selecting every nth chunk in list

Edited for the confusion in the problem, thanks for the answers!

My original problem was that I have a list [1,2,3,4,5,6,7,8], and I want to select every chunk of size x with gap of one. So if I want to select select every other chunk of size 2, the outcome would be [1,2,4,5,7,8]. A chunk size of three would give me [1,2,3,5,6,7].

I've searched a lot on slicing and I couldn't find a way to select chunks instead of element. Make multiple slice operations then join and sort seems a little too expensive. The input can either be a python list or numpy ndarray. Thanks in advance.

like image 229
jonathan chen Avatar asked Feb 17 '26 22:02

jonathan chen


2 Answers

To me it seems, you want to skip one element between chunks until the end of the input list or array.

Here's one approach based on np.delete that deletes that single elements squeezed between chunks -

out = np.delete(A,np.arange(len(A)/(x+1))*(x+1)+x)

Here's another approach based on boolean-indexing -

L = len(A)
avoid_idx = np.arange(L/(x+1))*(x+1)+x
out = np.array(A)[~np.in1d(np.arange(L),avoid_idx)]

Sample run -

In [98]: A = [51,42,13,34,25,68,667,18,55,32] # Input list

In [99]: x = 2

# Thus, [51,42,13,34,25,68,667,18,55,32]
                ^        ^         ^        # Skip these

In [100]: np.delete(A,np.arange(len(A)/(x+1))*(x+1)+x)
Out[100]: array([ 51,  42,  34,  25, 667,  18,  32])

In [101]: L = len(A)
     ...: avoid_idx = np.arange(L/(x+1))*(x+1)+x
     ...: out = np.array(A)[~np.in1d(np.arange(L),avoid_idx)]
     ...: 

In [102]: out
Out[102]: array([ 51,  42,  34,  25, 667,  18,  32])
like image 116
Divakar Avatar answered Feb 19 '26 10:02

Divakar


First off, you can create an array of indices then use np.in1d() function in order to extract the indices that should be omit then with a simple not operator get the indices that must be preserve. And at last pick up them using a simple boolean indexing:

>>> a = np.array([1,2,3,4,5,6,7,8])
>>> range_arr = np.arange(a.size)
>>> 
>>> a[~np.in1d(range_arr,range_arr[2::3])]
array([1, 2, 4, 6, 8])

General approach:

>>> range_arr = np.arange(np_array.size) 
>>> np_array[~np.in1d(range_arr,range_arr[chunk::chunk+1])]
like image 31
Mazdak Avatar answered Feb 19 '26 11:02

Mazdak



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!