You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Decimal模块在Streamlit中数据显示异常问题求助

解决Streamlit中Decimal类型DataFrame列显示异常问题

问题背景

为解决浮点数精度问题(例如Python中0.1 + 0.2 == 0.3结果为False),我用Decimal模块处理DataFrame中的欧元货币列,确保精确运算(Decimal('0.1')+Decimal('0.2') == Decimal('0.3')结果为True)。

在Jupyter Notebook中运行以下代码,输出完全正常:

d = {'name': ["A", "B", "C"], 'amount': [0.1, 0.2, 0.3]}
df = pd.DataFrame(data=d)
print("Original")
print(df)
print("Original_Test")
print(df['amount'][0]+df['amount'][1]==df['amount'][2])

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]]
print("Decimal Layout")
print(df)
print("Decimal Layout_Test")
print(df['amount'][0]+df['amount'][1]==df['amount'][2])

但适配到Streamlit后,尽管运算结果显示为True,amount列却错误显示为[1, 2, 3]而非预期的[0.1, 0.2, 0.3],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]]
st.write(df)
st.write(df['amount'][0]+df['amount'][1]==df['amount'][2])

问题原因

Streamlit的st.write()渲染DataFrame时,对Python标准库的Decimal类型处理逻辑与Jupyter不同。Jupyter会直接输出Decimal的字符串表示,而Streamlit在尝试解析Decimal类型时出现异常,导致只显示了数值的整数部分(如Decimal('0.1')被错误解析为1)。

解决方案

以下三种方法可解决该显示问题,同时保留Decimal的精确运算能力:

方法一:显示前将Decimal列转为格式化字符串

复制DataFrame用于显示,把Decimal列转换为带两位小数的字符串,既保证运算精度,又能正确显示格式:

import streamlit as st
import pandas as pd
from decimal import Decimal

d = {'name': ["A", "B", "C"], 'amount': [0.1, 0.2, 0.3]}
df = pd.DataFrame(data=d)
st.write("原始DataFrame")
st.write(df)

# 用Decimal处理列,保证运算精度
for col in df:
    if "amount" in col or "eur" in col:
        df[col] = [Decimal(str(round(i,2))) for i in df[col]]

# 复制DataFrame并格式化显示列
df_display = df.copy()
df_display['amount'] = df_display['amount'].apply(lambda x: f"{x:.2f}")
st.write("处理后的DataFrame")
st.write(df_display)

# 验证运算精度
st.write("运算精度验证结果:", df['amount'][0]+df['amount'][1]==df['amount'][2])

方法二:使用Pandas Styler格式化显示

利用Pandas的Styler工具直接格式化Decimal列的显示样式,无需转换数据类型:

import streamlit as st
import pandas as pd
from decimal import Decimal

d = {'name': ["A", "B", "C"], 'amount': [0.1, 0.2, 0.3]}
df = pd.DataFrame(data=d)
st.write("原始DataFrame")
st.write(df)

# 用Decimal处理列
for col in df:
    if "amount" in col or "eur" in col:
        df[col] = [Decimal(str(round(i,2))) for i in df[col]]

# 用Styler格式化显示
styler = df.style.format({'amount': lambda x: f"{x:.2f}"})
st.write("处理后的DataFrame")
st.write(styler)

st.write("运算精度验证结果:", df['amount'][0]+df['amount'][1]==df['amount'][2])

方法三:使用Pandas的Decimal数据类型

若你的Pandas版本支持(通常需1.3.0及以上),可指定列的dtype为'decimal',让Streamlit正确识别并渲染:

import streamlit as st
import pandas as pd
from decimal import Decimal

d = {'name': ["A", "B", "C"], 'amount': [0.1, 0.2, 0.3]}
df = pd.DataFrame(data=d)
st.write("原始DataFrame")
st.write(df)

# 转换为Pandas支持的Decimal dtype
for col in df:
    if "amount" in col or "eur" in col:
        df[col] = pd.Series([Decimal(str(round(i,2))) for i in df[col]], dtype='decimal')

st.write("处理后的DataFrame")
st.write(df)

st.write("运算精度验证结果:", df['amount'][0]+df['amount'][1]==df['amount'][2])

内容的提问来源于stack exchange,提问作者Andrea Farrugia

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.04 03:35:22