Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to always round up a XX.5 in numpy

I read that numpy is unbiased in rounding and that it works the way its designed. That "if you always round 0.5 up to the next largest number, then the average of a bunch rounded numbers is likely to be slightly larger than the average of the unrounded numbers: this bias or drift can have very bad effects on some numerical algorithms and make them inaccurate."

Disregarding this information and assuming that I always want to round up, how can I do it in numpy? Assuming my array can be quite large.

For simplicity, lets assume i have the array:

import numpy as np

A = [ [10, 15, 30], [25, 134, 41], [134, 413, 51]]
A = np.array(A, dtype=np.int16)

decimal = A * .1
whole = np.round(decimal)

decimal looks like:

[[  1.    1.5   3. ]
 [  2.5  13.4   4.1]
 [ 13.4  41.3   5.1]]

whole looks like:

[[  1.   2.   3.]
 [  2.  13.   4.]
 [ 13.  41.   5.]]

As you can see, 1.5 rounded to 2 and 2.5 also rounded to 2. How can I force to always get a round up answer for a XX.5? I know I can loop through the array and use python round() but that would definitely be much slower. Was wondering if there is a way to do it using numpy functions

like image 484
user1179317 Avatar asked Nov 08 '18 04:11

user1179317


People also ask

How to round up a number in NumPy?

Another method to round up a number is to use the numpy.ceil () method. First, we need to import the NumPy module in the script and then use the ceil () method to round up a number. The return type of the ceil () function is float, so even if the expression is in integers, the output will be in the float.

How to round off the array elements in Python?

By using thenp.round()method we can easily round off the array elements. In Python this method is a built-in function available in the NumPy module and this method if the floating values to be rounded are not given then by default it will consider as 0.

What is round up in Python?

The process of replacing a number by another number of approximately the same value but having fewer digits is known as rounding in Mathematics. If we round the number to an integer value slightly larger then the original number is known as rounding up. In this tutorial, we will learn about Python round up.

How to round a number to 2 decimal digits in Python?

There can be many methods to round a number up to 2 decimal digits in Python. For example one of the methods is to use the floating number method and specify the number of digits that we want. See the example below: Notice that in the above example, we have to round a number to 2 decimal digits.


2 Answers

The answer is almost never np.vectorize. You can, and should, do this in a fully vectorized manner. Let's say that for x >= 0, you want r = floor(x + 0.5). If you want negative numbers to round towards zero, the same formula applies for x < 0. So let's say that you always want to round away from zero. In that case, you are looking for ceil(x - 0.5) for x < 0.

To implement that for an entire array without calling np.vectorize, you can use masking:

def round_half_up(x):
    mask = (x >= 0)
    out = np.empty_like(x)
    out[mask] = np.floor(x[mask] + 0.5)
    out[~mask] = np.ceil(x[~mask] - 0.5)
    return out

Notice that you don't need to use a mask if you round all in one direction:

def round_up(x):
    return np.floor(x + 0.5)

Now if you want to make this really efficient, you can get rid of all the temp arrays. This will use the full power of ufuncs:

def round_half_up(x):
    out = x.copy()
    mask = (out >= 0)
    np.add(out, 0.5, where=mask, out=out)
    np.floor(out, where=mask, out=out)
    np.invert(mask, out=mask)
    np.subtract(out, 0.5, where=mask, out=out)
    np.ceil(out, where=mask, out=out)
    return out

And:

def round_up(x):
    out = x + 0.5
    np.floor(out, out=out)
    return out
like image 147
Mad Physicist Avatar answered Sep 29 '22 13:09

Mad Physicist


import numpy as np
A = [ [1.0, 1.5, 3.0], [2.5, 13.4, 4.1], [13.4, 41.3, 5.1]]
A = np.array(A)

print(A)

def rounder(x):
    if (x-int(x) >= 0.5):
        return np.ceil(x)
    else:
        return np.floor(x)

rounder_vec = np.vectorize(rounder)
whole = rounder_vec(A)
print(whole)

Alternatively, you can also look at numpy.ceil, numpy.floor, numpy.trunc for other rounding styles

like image 26
Andreas Avatar answered Sep 29 '22 15:09

Andreas