WXNerd
WXNerd

Reputation: 41

Find multiple values in python array close to given number

Using Python 2.7, I have an array of values that goes from ~0.000 to ~360.000 multiple times. I am trying to return all array indices with values closest to 147.010 (even duplicate values), so I can use each of these indices later on. For example, a smaller sample from one array is:

array([  146.749,  147.249,  147.749,  146.749,  147.249,  147.749,  146.749,  147.263,  147.749,  146.472,  147.469,  148.471])

I am looking for an array, or list, of indices closest to 147.01, in this case would be:

1, 4, 7, 10

I have tried this:

min(range(len(array)), key=lambda i: abs(array[i]-some_value))

but this only returns one index, when multiple indices are needed. I looked but have not found a similar question or answer. Thank you for any help.

Upvotes: 4

Views: 3158

Answers (3)

fips
fips

Reputation: 4379

If you like one-liners, take k = 147.01 then you can do:

print [i for i, v in enumerate(array) if abs(v - k) == min([abs(x - k) for x in array])]

Outputs: [1, 4]

It will print as many n indexes of elements equally close to k. In your list elements at index 7, 10 are not equally close, can you double check those numbers?

EDIT: Let's see one by one, using the array from the question:

[146.749,  147.249,  147.749,  146.749,  147.249,  147.749,  146.749,  147.263,  147.749,  146.472,  147.469,  148.471]

Distances for elements at indexes: 1, 4, 7, 10:

index = 1,  abs(147.249 - 147.01) = 0.239
index = 4,  abs(147.249 - 147.01) = 0.239
index = 7,  abs(147.263 - 147.01) = 0.253
index = 10, abs(147.469 - 147.01) = 0.459

According to these numbers, elements at indexes 1, 4 have a smaller distance from 147.01 than 7, 10. Isn't this what you meant?

Upvotes: 0

smac89
smac89

Reputation: 43196

If you sort the array in the order the elements are away from the pivot, then you will be able to take the first k elements and those are the ones closest to the element you are looking at

def k_closest(sample, pivot, k):
    return sorted(sample, key=lambda i: abs(i - pivot))[:k]

Example:

>>> l = [1,2,3,4]
>>> k_closest(l, 3, 2)
[3,2]
>>> k_closest(l, 3, 3)
[3,2,4]

To get the index of the elements as well, you can do this:

def k_closest(sample, pivot, k):
    return sorted(enumerate(sample), key=lambda (n, v): abs(v - pivot))[:k]

Running it with the same elements as before, we get

>>> l = [1,2,3,4]
>>> k_closest(l, 3, 2)
[(2, 3), (1, 2)]
>>> k_closest(l, 3, 3)
[(2, 3), (1, 2), (3, 4)]

For each tuple in the list, the first element is the index in the original array and the second is the number you are actually interested in

If you just want the index, you can tweak the function a bit to become

import operator

def k_closest(sample, pivot, k):
    return map(operator.itemgetter(0), sorted(enumerate(sample), key=lambda (n, v): abs(v - pivot)))[:k]

Running with the original input, will now give you

>>> k_closest(l, 3, 2)
[2, 1]
>>> k_closest(l, 3, 3)
[2, 1, 3]

Upvotes: 5

sebastianspiegel
sebastianspiegel

Reputation: 455

You can go through and find the keys corresponding to the closest values. Then append the values corresponding to those keys to a list.

new_array = map(lambda x: abs(x-some_value),my_array)

min_value=min(new_array)

Now find the indices of the new value

my_keys = []
for i,val in enumerate(new_array):
    if val == min_value:
        my_keys.append(i)

Finally create your output list.

my_answer=[]
for i in my_keys:
    my_answer.append(my_array[i])

Upvotes: 0

Related Questions