Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Round in numpy to Nearest Step

I would like to know how I can round a number in numpy to an upper or lower threshold which is function of predefined step size. Hopefully stated in a clearer way, if I have the number 123 and a step size equal to 50, I need to round 123 to the closest of either 150 or 100, in this case 100. I came out with function below which does the work but I wonder if there is a better, more succint, way to do this.

Thanks in advance,

Paolo

def getRoundedThresholdv1(a, MinClip):
    import numpy as np
    import math
    digits = int(math.log10(MinClip))+1
    b = np.round(a, -digits)
    if b > a:  # rounded-up
        c = b - MinClip
        UpLow = np.array((b,c))
    else:  # rounded-down
        c = b + MinClip
        UpLow = np.array((c,b))
    AbsDelta = np.abs(a - UpLow)
    return UpLow[AbsDelta.argmin()]




getRoundedThresholdv1(143, 50)
like image 403
RandomCPlusPlus Avatar asked Oct 22 '11 11:10

RandomCPlusPlus


People also ask

How do you round to the nearest whole number on a NumPy?

To round elements of the array to the nearest integer, use the numpy. rint() method in Python Numpy. For values exactly halfway between rounded decimal values, NumPy rounds to the nearest even value. The out is a location into which the result is stored.

How do you round a number to the nearest in Python?

ceil(). To round down to the nearest integer, use math. floor(). To round a number to a number of decimals, give the round() function a second argument.

How do you round down to the nearest 5 in Python?

floor() function is used to round a number down, while the math. ceil() function is used to round a number up.


2 Answers

The solution by pb360 is much better, using the second argument of builtin round in python3.

I think you don't need numpy:

def getRoundedThresholdv1(a, MinClip):
    return round(float(a) / MinClip) * MinClip

here a is a single number, if you want to vectorize this function you only need to replace round with np.round and float(a) with np.array(a, dtype=float)

like image 50
Ruggero Turra Avatar answered Oct 04 '22 02:10

Ruggero Turra


Summary: This is a correct way to do it, the top answer has cases that do not work:

def round_step_size(quantity: Union[float, Decimal], step_size: Union[float, Decimal]) -> float:
    """Rounds a given quantity to a specific step size
    :param quantity: required
    :param step_size: required
    :return: decimal
    """
    precision: int = int(round(-math.log(step_size, 10), 0))
    return float(round(quantity, precision))

My reputation is too low to post a comment on the top answer from Ruggero Turra and point out the issue. However it has cases which did not work for example:

def getRoundedThresholdv1(a, MinClip):
    return round(float(a) / MinClip) * MinClip

getRoundedThresholdv1(quantity=13.200000000000001, step_size=0.0001)

Returns 13.200000000000001 right back whether using numpy or the standard library round. I didn't even find this by stress testing the function. It just came up when using it in production code and spat an error.

Note full credit for this answer comes out of an open source github repo which is not mine found here

like image 42
pb360 Avatar answered Oct 05 '22 02:10

pb360