python: round float values to interval limits / grid

The name of the picture


python: round float values to interval limits / grid



I've got an array of (random) floating point numbers. I want to round each value up to a limit of an arbitrary grid. See the following example:


import numpy as np
np.random.seed(1)

# setup
sample = np.random.normal(loc=20, scale=6, size=10)
intervals = [-np.inf, 10, 12, 15, 18, 21, 25, 30, np.inf]

# round each interval up
for i in range(len(intervals) - 1):
sample[np.logical_and(sample > intervals[i], sample <= intervals[i+1])] = intervals[i+1]



This results in:


[ 30. 18. 18. 15. 30. 10. inf 18. 25. 21.]



My question is: How can I avoid the for-loop? I'm sure there's some way using numpy's array magic that I don't see right now.




4 Answers
4



If intervals is sorted, you can use np.searchsorted:


intervals


np.searchsorted


np.array(intervals)[np.searchsorted(intervals, sample)]
# array([ 30., 18., 18., 15., 30., 10., inf, 18., 25., 21.])



searchsorted returns the index of the interval where the element belongs to:


searchsorted


np.searchsorted(intervals, sample)
# array([7, 4, 4, 3, 7, 1, 8, 4, 6, 5])



The default side='left' returns the smallest index of such interval and the result falls into the left open, right close scenario.


side='left'



Did not run a check but:


from bisect import bisect

for index, value in enumerate(sample):
sample[index] = intervals[ bisect( intervals, value)]



You can use Pandas cut():


cut()


import pandas as pd

pd.cut(sample, intervals, labels=intervals[1:]).tolist()



If values is a 1D arrays with your values, you could do something like


values


diff = values < intervals[:, None]
t = np.argmax(diff, axis=0)
new_values = intervals[t]






By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Popular posts from this blog

Stripe::AuthenticationError No API key provided. Set your API key using “Stripe.api_key = ”

CRM reporting Extension - SSRS instance is blank

Keycloak server returning user_not_found error when user is already imported with LDAP