必须分段控制读取、计算、导出三环节:read_csv时用dtype=str保原始字符;计算时对需运算列用pd.to_numeric(..., errors="coerce")显式转换;to_csv前将关键列astype(str)并禁用float_format,确保csv中数字完整无科学计数法。

直接用 float64 做大整数或高精度小数计算,大概率会丢精度——这不是 bug,是 IEEE 754 浮点表示的固有限制。关键不在“怎么修”,而在“在哪修”:读取、计算、导出三个环节都可能出问题,必须分段控制。
read_csv 时就别让精度进内存
CSV 里存着 18 位数字(比如时间戳、ID、金额),pd.read_csv() 默认按 float 推断类型,一读就变科学计数法或截断。最稳做法是先当字符串读进来:
-
pd.read_csv("data.csv", dtype=str)—— 全列转 string,保原始字符不丢失 - 再对需要计算的列,用
pd.to_numeric(..., errors="coerce")显式转数值(注意加errors="coerce"防止非数字报错) - 如果该列本就是整型且超
2**53(约 9e15),别强转int64或float64,直接留str或改用pd.Int64Dtype()(支持 nullable int)
pivot_table 里整数变浮点是默认行为
pivot_table 内部会对整型 values 列自动 downcast 成 float,哪怕你设了 aggfunc=lambda x: x,源码里那段 maybe_downcast_to_dtype 仍会触发。结果就是 1382441313687 → 1.38244131369e+12。
- 绕过方法:把
values列提前转成str,再传给pivot_table,并确保aggfunc返回原样(如aggfunc="first"或lambda x: x.iloc[0]) - 副作用:内存上涨,且后续无法直接做数值运算——得在 pivot 后再统一转回数值(如果真需要)
- 替代方案:不用
pivot_table,改用groupby().agg(...)+unstack(),能更好控制中间 dtype
to_csv 导出时 float_format 不解决根本问题
float_format='%.10f' 只是格式化输出,底层还是 float,一旦数字超过 15–16 位有效数字,写进 CSV 的已经是近似值。更糟的是,再用 read_csv 读回来,又进一次 float 解析循环。
- 真正防丢精度的导出:对关键列先
df["col"] = df["col"].astype(str),再to_csv(..., float_format=None) - 如果列含混合类型(比如数字+空值),
astype(str)会把NaN变成字符串"nan",需提前用df["col"] = df["col"].fillna("")处理 - 导出后验证:用文本编辑器打开 CSV,确认长数字是否完整、无
e+记号
精度不是“算完再修”,而是从第一行 read_csv 就得决定数据以什么形态存在内存里——字符串最安全,但代价是不能直接参与数值运算;Decimal 更准但慢且不兼容 pandas 原生运算;float64 最快但只适合 ≤15 位有效数字的场景。选哪条路,取决于你的数据本质:是 ID/编码(必须精确),还是测量值(允许微小误差)。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











