Pandas精度失效问题解析及解决方案
2025-01-29 21:48:47
Pandas 显示精度失效的常见问题
使用 pandas 处理数据时,控制输出的数值精度非常常见。 但有时,你会发现设置了全局显示精度选项,例如 pd.option_context('display.precision', 0)
,对 DataFrame 的部分列,尤其是最后一列,不起作用,呈现出类似科学计数法的输出。这种不一致的行为会影响数据展示和分析的准确性,需要特别留意。
问题分析
这个问题通常不是 pandas 本身错误导致的,而是和 pandas 内部显示机制有关。 pandas 为了更紧凑的呈现数据,会自动调整数字格式。 这包括,在某些情况下为了节约空间可能会将超出一定范围或精度的数字采用科学计数法表示。 这种机制对于前面的列一般工作良好,但在一些边缘情况,可能没有办法完全按照display.precision
里的设置完全匹配用户的意图,特别是当涉及到最后一列的数据展示时,可能会因内部计算导致不必要的精度损失,造成看起来不应用科学计数法的场景,仍以科学计数法输出。
解决方案一:调整显示选项和浮点格式化
第一个解决方案,可以更具体地调整 display.float_format
,结合display.precision
设置精度来直接控制浮点数输出。这个方法让你可以针对 DataFrame 中浮点数值,定制化输出格式。
操作步骤:
- 使用
pd.option_context
配置全局显示选项,不仅要设置精度,同时设定自定义格式化函数来控制浮点数格式。 - 将 DataFrame 传入此上下文进行显示。
import pandas as pd
import numpy as np
# 构造一个测试DataFrame
data = {'gas': [818.851398, 2009.784005, 2304.134123, 2647.367761, 1685.694664, 1588.714377, 1376.973210, 605.798978, 117.488287, 163.644399, 129.027315, 625.730027],
'prev': [np.nan, 1755.768035, 2479.160200, 2524.686911, 2070.363903, 1840.684792, 1385.102980, 706.870375, 155.409729, 133.852727, 121.264696, 198.051683],
'delta%': [np.nan, 14.467513, -7.059894, 4.859250, -18.579789, -13.688950, -0.586943, -14.298434, -24.400945, 22.257053, 6.401384, 215.942797]}
dfy = pd.DataFrame(data, index = pd.to_datetime(['2023-10-01','2023-11-01','2023-12-01','2024-01-01','2024-02-01','2024-03-01','2024-04-01','2024-05-01','2024-06-01','2024-07-01','2024-08-01','2024-09-01']))
print(dfy)
print(dfy.dtypes)
with pd.option_context('display.precision', 0, 'display.float_format', lambda x: '%.0f' % x):
print(dfy)
上述代码通过 lambda 函数lambda x: '%.0f' % x
来指定浮点数的输出格式,使其不使用科学计数法, 并指定输出 0 位小数。 这确保了 DataFrame 整体,包括最后一列按照指定精度正确输出,。 %.0f
表示格式化浮点数为没有小数位的字符串。
解决方案二: 转化为字符串类型后输出
在极少数情况下,上述方法无法奏效,可以通过先将最后一列转为字符串类型,再进行输出的方式。 由于不再被 pandas 当作数值类型,便不会受到默认的格式化影响, 可以解决特殊场景的精度控制问题。
操作步骤:
- 将最后一列使用
astype(str)
方法转化为字符串类型。 - 使用原始配置打印DataFrame。
- 无需重新配置pandas全局显示精度,保持原本的精度设置
import pandas as pd
import numpy as np
# 构造一个测试DataFrame
data = {'gas': [818.851398, 2009.784005, 2304.134123, 2647.367761, 1685.694664, 1588.714377, 1376.973210, 605.798978, 117.488287, 163.644399, 129.027315, 625.730027],
'prev': [np.nan, 1755.768035, 2479.160200, 2524.686911, 2070.363903, 1840.684792, 1385.102980, 706.870375, 155.409729, 133.852727, 121.264696, 198.051683],
'delta%': [np.nan, 14.467513, -7.059894, 4.859250, -18.579789, -13.688950, -0.586943, -14.298434, -24.400945, 22.257053, 6.401384, 215.942797]}
dfy = pd.DataFrame(data, index = pd.to_datetime(['2023-10-01','2023-11-01','2023-12-01','2024-01-01','2024-02-01','2024-03-01','2024-04-01','2024-05-01','2024-06-01','2024-07-01','2024-08-01','2024-09-01']))
print(dfy)
print(dfy.dtypes)
with pd.option_context('display.precision', 0):
dfy['delta%'] = dfy['delta%'].astype(str)
print(dfy)
本方案,通过修改 dfy['delta%'] = dfy['delta%'].astype(str)
代码将 delta%
列转化为字符串类型。 这时 display.precision
设置的精度值会失效。 该列输出字符串值,无需 pandas 的数值格式化。 如果不希望最后一列受到显示精度的影响,需要原样显示内容, 可以考虑此种方式。 需要注意转换成字符型后会损失数值精度。 如果对数值进行进一步操作和分析, 仍需要转回数值类型。
注意事项
在处理 pandas 输出显示精度时, 一定注意理解 pandas 显示逻辑, 并根据需要选择合适的显示配置。 在涉及重要的数值精度时, 请务必检验结果是否正确。 尤其是当你发现某些列(特别是最后一列)的输出行为与其他列不一致的时候,仔细检查并测试这些方法以确保准确的呈现结果,满足项目的数据展示需求。