Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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.]

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.

like image 388
ascripter Avatar asked Jul 24 '18 15:07

ascripter


2 Answers

If intervals is sorted, you can use 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:

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.

like image 112
Psidom Avatar answered Oct 16 '22 02:10

Psidom


You can use Pandas cut():

import pandas as pd

pd.cut(sample, intervals, labels=intervals[1:]).tolist()
like image 25
andrew_reece Avatar answered Oct 16 '22 00:10

andrew_reece