Select N evenly spaced out elements in array, including first and last

Question:

I have an array of arbitrary length, and I want to select N elements of it, evenly spaced out (approximately, as N may be even, array length may be prime, etc) that includes the very first arr[0] element and the very last arr[len-1] element.

Example:

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

Then I want to make a function like the following to grab numElems evenly spaced out within the array, which must include the first and last element:

GetSpacedElements(numElems = 4)
>>> returns 0, 5, 11, 16

Does this make sense?

I’ve tried arr[0:len:numElems] (i.e. using the array start:stop:skip notation) and some slight variations, but I’m not getting what I’m looking for here:

>>> arr[0:len:numElems]
array([ 0,  4,  8, 12, 16])

or

>>> arr[0:len:numElems+1]
array([ 0,  5, 10, 15])

I don’t care exactly what the middle elements are, as long as they’re spaced evenly apart, off by an index of 1 let’s say. But getting the right number of elements, including the index zero and last index, are critical.

Asked By: JDS

||

Answers:

To get a list of evenly spaced indices, use np.linspace:

idx = np.round(np.linspace(0, len(arr) - 1, numElems)).astype(int)

Next, index back into arr to get the corresponding values:

arr[idx]

Always use rounding before casting to integers. Internally, linspace calls astype when the dtype argument is provided. Therefore, this method is NOT equivalent to:

# this simply truncates the non-integer part
idx = np.linspace(0, len(array) - 1, numElems).astype(int)
idx = np.linspace(0, len(arr) - 1, numElems, dtype='int')
Answered By: cs95

Your GetSpacedElements() function should also take in the array to avoid unfortunate side effects elsewhere in code. That said, the function would need to look like this:

import numpy as np

def GetSpacedElements(array, numElems = 4):
    out = array[np.round(np.linspace(0, len(array)-1, numElems)).astype(int)]
    return out

arr = np.arange(17)
print(array)
spacedArray = GetSpacedElements(arr, 4)
print (spacedArray)
Answered By: Justin

If you want to know more about finding indices that match values you seek, also have a look at numpy.argmin and numpy.where. Implementing the former:

import numpy as np

test = np.arange(17)

def nearest_index(array, value):
    return (np.abs(np.asarray(array) - value)).argmin()

def evenly_spaced_indices(array, steps):
    return [nearest_index(array, value) for value in np.linspace(np.min(array), np.max(array), steps)]

print(evenly_spaced_indices(test,4))

You should keep in mind that this is an unnecessary amount of function calls for the initial question you asked as switftly demonstrated by coldspeed. np.round intuitively rounds to the closest matching integer serving as index, implementing a similar process but optimised in C++. If you are interested in the indices too, you could have your function simply return both:

import numpy as np

def GetSpacedElements(array, numElems=4, returnIndices=False):
    indices = np.round(np.linspace(0, len(arr) - 1, numElems)).astype(int)
    values = array[indices]
    return (values, indices) if returnIndices else (values)

arr = np.arange(17) + 42
print(arr)
print(GetSpacedElements(arr, 4))                            # values only
print(GetSpacedElements(arr, 4, returnIndices=True)[0])     # values only
print(GetSpacedElements(arr, 4, returnIndices=True)[1])     # indices only
Answered By: ddelange

To get N evenly spaced elements from list ‘x’:

x[::int(np.ceil( len(x) / N ))]
Answered By: Shahrab Khan Sami
Categories: questions Tags: , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.