decimal.InvalidOperation error when rounding values in Series
Asked Answered
I

2

8

Series I'm working with:

import pandas as pd
from decimal import Decimal, BasicContext

df = pd.Series([14978.22,
16025.429160000002,
209.97803999999996,
618.20369,
605.607,
1431.0916,
30.53575,
23.77272,
404.79368999999997,
55580.152319999994
])
df2 = df.apply(str).apply(Decimal, context=BasicContext)

I'd like to round all the values in df to 5 digits using "ROUND_HALF_UP" (which is the rounding used for BasicContext). So, I do this:

df2.apply(round, ndigits=5)

However, this throws an error:

Traceback (most recent call last):

File "", line 1, in df2.apply(round, ndigits=5)

File "C:\Users\Guest\AppData\Roaming\Python\Python36\site-packages\pandas\core\series.py", line 3194, in apply mapped = lib.map_infer(values, f, convert=convert_dtype)

File "pandas/_libs/src\inference.pyx", line 1472, in pandas._libs.lib.map_infer

File "C:\Users\Guest\AppData\Roaming\Python\Python36\site-packages\pandas\core\series.py", line 3181, in f = lambda x: func(x, *args, **kwds)

InvalidOperation: class 'decimal.InvalidOperation'

However, rounding to 4 digits works:

df2.apply(round, ndigits=4)

Why is this happening and how do I work around this?

Incombustible answered 10/8, 2018 at 20:7 Comment(3)
round applied to a Decimal object requires that the current Decimal context has sufficient precision to represent the result. The BasicContext you're using has a precision of 9, but 16025.429160000002 rounded to 5 places after the point requires 10 significant digits to represent.Chariness
@MarkDickinson, any chance you could promote that comment to an answer?Maybellemayberry
@Maybellemayberry Sorry, I don't have a lot of cycles available for Stack Overflow answers these days. But you should feel free to use the content of that comment in your own answer.Chariness
C
4

Have you tried catching the decimal.InvalidOperation exception? You should have a try and except.

try:
    # your code 
except DecimalException as e:
    print(e)
Creon answered 11/8, 2018 at 18:7 Comment(0)
L
1

Calling round on a Decimal object requires that the current Decimal context has sufficient precision to represent the result. The BasicContext you're using has a precision of 9, but 16025.429160000002 rounded to 5 places after the point requires 10 significant digits to represent.

Calling round and specifying a rounding precision on an instance of the Decimal class uses the quantize function. quantize raises decimal.InvalidOperation "if the length of the coefficient after the quantize operation would be greater than precision" (decimal documentation on python.org).

Lombroso answered 4/6 at 17:36 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.