I have a dataframe where one of the columns deals with currency displayed in Euros. Due to the rounding issues I want to use the DECIMAL module to have precise arithmetic outcomes.
Python command: 0.1 + 0.2 == 0.3 is FALSE
Decimal module: Decimal(β0.1β)+Decimal(β0.2β) == Decimal(β0.3β) is TRUE (This is the scenario I am looking for)
Steps to reproduce
Code snippet Streamlit:
d = {'name': ["A", "B", "C"], 'amount': [0.1, 0.2, 0.3]}
df = pd.DataFrame(data=d)
st.write(df)
for col in df:
if "amount" in col or "eur" in col:
df[col] = list(df[col])
df[col] = [Decimal(str(round(i,2))) for i in df[col]]
#Output dataframe
st.write(df)
#Testing Condition
st.write(df['amount'][0]+df['amount'][1]==df['amount'][2])
Expected behavior:
Actual behavior:
Amount column is incorrectly displayed at 1, 2 ,3 instead of 0.1, 0.2, 0.3.
Testing condition is correctly represented as true
Please upvote the issue on GitHub if you want our engineers to prioritize a fix.
The only workarounds until the bug is patched are to either:
Cast the column to numpy.float64 with pd.to_numeric ( A possible problem with to_numeric is that since a Decimal number has arbritary precision, it might not be representable by either integer or float types) or
Cast the column to str
Option 1:
d = {"name": ["A", "B", "C"], "amount": [0.1, 0.2, 0.3]}
df = pd.DataFrame(data=d)
st.write(df)
for col in df:
if "amount" in col or "eur" in col:
df[col] = list(df[col])
df[col] = [Decimal(str(round(i, 2))) for i in df[col]]
# Output dataframe
df.amount = df.amount.apply(pd.to_numeric)
st.write(df)
# Testing Condition
st.write(df["amount"][0] + df["amount"][1] == df["amount"][2]) # Evaluates to False
Option 2:
d = {"name": ["A", "B", "C"], "amount": [0.1, 0.2, 0.3]}
df = pd.DataFrame(data=d)
st.write(df)
for col in df:
if "amount" in col or "eur" in col:
df[col] = list(df[col])
df[col] = [Decimal(str(round(i, 2))) for i in df[col]]
# Output dataframe
df.amount = df.amount.apply(str)
st.write(df)
# Testing Condition
st.write(df["amount"][0] + df["amount"][1] == df["amount"][2])
Thanks a lot for the quick reply. I look at the two options that you posted. Unfortunately, the Testing condition would then be False once the value is changed back to numeric or string.
Sorry for the stupid question but I am still new to github. How can I upvote this issue please?
Additionally, you could also add a comment to the bottom of the issue, saying youβre running into the bug and a sentence about why a fix is important for your use case:
Could you use floats and implement your own rounding for the equality test? Since you are working with currencies the floating point error should always be many orders of magnitude smaller than the precision you need.