JakoBrix
JakoBrix

Reputation: 11

Find the closest value above and under in an array?

I have an array which is consisting of [An elementnumber, x-coordinate, y-coordinate, z-coordinate, radius(polare coordinates), θ(polare coordinates)] In this array i need to find the two closest values to a specified number, the one above and the one below. This needs to be found in the last columns of the array which holds the θ value.

The range of the values goes from 0 - 1.5707 radian(0 - 90 degrees) and in our case we want to be able to choose the amount of specified numbers we want

number=9 
Anglestep = math.pi/2 / number 
Anglerange = np.arange(0,math.pi/2+anglestep,anglestep) #math.pi/2+anglestep so that we get math.pi/2 in   the array

For an example i need to find the two values above and under the specified value: "0.17"

[...['4549', '4.2158604', '49.4799309', '0.0833661', 49.65920902290997, 0.0849981532744405],
 ['4535', '4.2867651', '49.4913025', '0.0813997', 49.67660795755971, 0.08640089283783374],
 ['4537', '5.6042995', '49.4534569', '0.0811241', 49.7699967073121, 0.11284330708918186],
 ['4538', '6.2840257', '49.4676971', '0.0809942', 49.86523874780516, 0.12635612935285648],
 ['4539', '6.9654546', '49.4909363', '0.0814121', 49.97869879894153, 0.13982362821749783],
 ['4540', '7.6476088', '49.5210190', '0.0813955', 50.10805567128103, 0.1532211602749019],
 ['4541', '8.3298655', '49.5605049', '0.0812513', 50.25564948531672, 0.16651831290560243],
 ['4542', '9.0141211', '49.6065178', '0.0811457', 50.41885547537927, 0.17975113416156624],
 ['4529', '9.3985014', '49.6320610', '0.0812080', 50.51409018950577, 0.18714756393388338],
 ['4531', '10.3884563', '49.7157669', '0.0812043', 50.78954127329902, 0.2059930152826599]..]

So what i want as output would in this case be the two values: (0.16651831290560243, 0.17975113416156624)

Upvotes: 1

Views: 1838

Answers (2)

askewchan
askewchan

Reputation: 46578

@NPE's answer is correct for a 1d array, but you must first access the Angle column of your array. This depends on the dtype (data type) of your array (your array seems to include both strings and floats, which is not allowed for a numpy array). There are two ways that it might be solved, one by making it all floats, the other by using a structured dtype:

All floats

arr = np.array([
    ['4549',  '4.2158604', '49.4799309', '0.0833661', 49.65920902290997, 0.0849981532744405 ],
    ['4535',  '4.2867651', '49.4913025', '0.0813997', 49.67660795755971, 0.08640089283783374],
    ['4537',  '5.6042995', '49.4534569', '0.0811241', 49.7699967073121 , 0.11284330708918186],
    ['4538',  '6.2840257', '49.4676971', '0.0809942', 49.86523874780516, 0.12635612935285648],
    ['4539',  '6.9654546', '49.4909363', '0.0814121', 49.97869879894153, 0.13982362821749783],
    ['4540',  '7.6476088', '49.5210190', '0.0813955', 50.10805567128103, 0.1532211602749019 ],
    ['4541',  '8.3298655', '49.5605049', '0.0812513', 50.25564948531672, 0.16651831290560243],
    ['4542',  '9.0141211', '49.6065178', '0.0811457', 50.41885547537927, 0.17975113416156624],
    ['4529',  '9.3985014', '49.6320610', '0.0812080', 50.51409018950577, 0.18714756393388338],
    ['4531', '10.3884563', '49.7157669', '0.0812043', 50.78954127329902, 0.2059930152826599 ]], dtype=float)

Then, to apply @Jaime's method, use

i = np.searchsorted(arr[:, -1], 0.17)
below = arr[i-1]
above = arr[i]

below
# array([  4.54100000e+03,   8.32986550e+00,   4.95605049e+01,   8.12513000e-02,   5.02556495e+01,   1.66518313e-01])
above
# array([  4.54200000e+03,   9.01412110e+00,   4.96065178e+01,   8.11457000e-02,   5.04188555e+01,   1.79751134e-01])

If you want just the angles, then just slice by column as well:

below_ang = arr[i-1, -1]
above_ang = arr[i, -1]

below_ang, above_ang
#(0.166518313, 0.179751134)

Note that this assumes that arr is sorted by angle.

Structured array:

arr = array([ ('4549',  '4.2158604', '49.4799309', '0.0833661', 49.65920902290997, 0.0849981532744405 ),
              ('4535',  '4.2867651', '49.4913025', '0.0813997', 49.67660795755971, 0.08640089283783374),
              ('4537',  '5.6042995', '49.4534569', '0.0811241', 49.7699967073121 , 0.11284330708918186),
              ('4538',  '6.2840257', '49.4676971', '0.0809942', 49.86523874780516, 0.12635612935285648),
              ('4539',  '6.9654546', '49.4909363', '0.0814121', 49.97869879894153, 0.13982362821749783),
              ('4540',  '7.6476088', '49.5210190', '0.0813955', 50.10805567128103, 0.1532211602749019 ),
              ('4541',  '8.3298655', '49.5605049', '0.0812513', 50.25564948531672, 0.16651831290560243),
              ('4542',  '9.0141211', '49.6065178', '0.0811457', 50.41885547537927, 0.17975113416156624),
              ('4529',  '9.3985014', '49.6320610', '0.0812080', 50.51409018950577, 0.18714756393388338),
              ('4531', '10.3884563', '49.7157669', '0.0812043', 50.78954127329902, 0.2059930152826599)], 
             dtype=[('id', 'S4'), ('x', 'S10'), ('y', 'S10'), ('z', 'S9'), ('rad', '<f8'), ('ang', '<f8')])

i = np.searchsorted(arr['ang'], 0.17)
below = arr[i-1]
above = arr[i]

below
# ('4541', '8.3298655', '49.5605049', '0.0812513', 50.25564948531672, 0.16651831290560243)
above
# ('4542', '9.0141211', '49.6065178', '0.0811457', 50.41885547537927, 0.17975113416156624)

Doing it for several values

First, an easier way to set up your range is with linspace, which automatically includes the start and end, and is specified by length of array, not step. Instead of:

number=9 
anglestep = math.pi/2 / number 
anglerange = np.arange(0,math.pi/2+anglestep,anglestep) #math.pi/2+anglestep so that we get math.pi/2 in the array

Use

number = 9
anglerange = np.linspace(0, math.pi/2, number) # start, end, number

Now, searchsorted will actually find several points for you just as easily:

locs = np.searchsorted(arr['ang'], anglerange)
belows = arr['ang'][locs-1]
aboves = arr['ang'][locs]

For example, I'll set anglerange = [0.1, 0.17, 0.2] since the full range isn't in your sample data:

belows
# array([ 0.08640089,  0.16651831,  0.18714756])
aboves
# array([ 0.11284331,  0.17975113,  0.20599302])

Upvotes: 1

NPE
NPE

Reputation: 500893

In [30]: np.max(arr[arr < .17])
Out[30]: 0.16651831290560243

In [31]: np.min(arr[arr > .17])
Out[31]: 0.17975113416156624

Upvotes: 1

Related Questions