Python学习笔记: Pandas 成绩四捨五入的正确处理方式

本文同步发表于小弟自架网站(非钓鱼也无广告,纯分享):

微确幸资讯站

承接上一篇的说明,以前都直接的用round函数(四捨六入五成双)来处理四捨五入,
在一般的数据计算上,这种处理方式其实是比较科学的。
round函数可以在多次重複计算下,减少数据的误差,
比我们传统认知的四捨五入好。

但有些场合要做的是依四捨五入的定义,明确比较大小,
这时候使用round函数就是一个很大的坑了!!

但在进入主题之前,我们应该先对程式中的浮点数有一个概念,
这部份可以参考一下Python的说明文件:
浮点数运算:问题与限制
以及以下网址的说明:
Python 的 round() 与 decimal 模组

接下来可以先来看一下我创建的数据,以及使用decimal模组执行的结果:

import pandas as pdfrom decimal import Decimal, ROUND_UP, ROUND_DOWN, ROUND_HALF_UP, ROUND_HALF_DOWN, ROUND_HALF_EVEN, ROUND_FLOOR, ROUND_CEILINGdf = pd.DataFrame(data=[3.115, 3.225, 3.335, 3.445, 3.555, 3.665, 3.775, 3.885, 3.995], columns=['範例数据'])df['浮点数结果'] = df['範例数据'].apply(lambda x: "{:1.20f}".format(x))df['round结果'] = df['範例数据'].round(2)df['ROUND_UP结果'] = df['範例数据'].apply(lambda x: Decimal(str(x)).quantize(Decimal('.00'), ROUND_UP))df['ROUND_DOWN结果'] = df['範例数据'].apply(lambda x: Decimal(str(x)).quantize(Decimal('.00'), ROUND_DOWN))df['ROUND_HALF_UP结果'] = df['範例数据'].apply(lambda x: Decimal(str(x)).quantize(Decimal('.00'), ROUND_HALF_UP))df['ROUND_HALF_DOWN结果'] = df['範例数据'].apply(lambda x: Decimal(str(x)).quantize(Decimal('.00'), ROUND_HALF_DOWN))df['ROUND_HALF_EVEN结果'] = df['範例数据'].apply(lambda x: Decimal(str(x)).quantize(Decimal('.00'), ROUND_HALF_EVEN))df['ROUND_FLOOR结果'] = df['範例数据'].apply(lambda x: Decimal(str(x)).quantize(Decimal('.00'), ROUND_FLOOR))df['ROUND_CEILING结果'] = df['範例数据'].apply(lambda x: Decimal(str(x)).quantize(Decimal('.00'), ROUND_CEILING))df

http://img2.58codes.com/2024/20122335XrsZgGmkKS.jpg

参考上面的浮点数结果,其实就是程式中真正拿来运算的值。
所以round函数其实是以最接近的值来做修整!!

因为用浮点数来运算有限制及问题,我们只能依自己的需求,
设定你要的结果。

比如说很多学校招生简章都会说明四捨五入来计算成绩,
但如果我们用了round函数,就会产生误差,可能造成后续的纠纷。

举例来说,招生考试的评分项目有以下二项:

资审成绩(由3个老师评分后,计算平均分数后四捨五入至小数第2位)。面试成绩(由3个老师评分后,计算平均分数后四捨五入至小数第2位)。

「资审成绩」佔总成绩50%,面试成绩佔总成绩50%,计算方式定义如下:
总成绩 = 资审成绩*0.5(四捨五入取至小数点第2位) + 面试成绩*0.5(四捨五入取至小数点第2位)

接下来看一下程式实作的範例:

import numpy as npimport pandas as pdfrom decimal import Decimal, ROUND_HALF_UP# 产生8列6栏介于0-100的DataFramedf = pd.DataFrame(np.random.uniform(40,100,size=(8, 2)), columns=['资审平均成绩', '面试平均成绩'])df

http://img2.58codes.com/2024/20122335MRq6cybI72.jpg

# 先用decimal模组的ROUND_HALF_UP做四捨五入取到小数点第二位df['资审四捨五入成绩'] = df['资审平均成绩'].apply(lambda x: Decimal(str(x)).quantize(Decimal('.00'), ROUND_HALF_UP))df['面试四捨五入成绩'] = df['面试平均成绩'].apply(lambda x: Decimal(str(x)).quantize(Decimal('.00'), ROUND_HALF_UP))df

http://img2.58codes.com/2024/20122335z2aVPfeXtD.jpg

# 确定一下程式中四捨五入成绩的浮点数值df['资审四捨五入成绩_浮点数'] = df['资审四捨五入成绩'].apply(lambda x: "{:1.20f}".format(x))df['面试四捨五入成绩_浮点数'] = df['面试四捨五入成绩'].apply(lambda x: "{:1.20f}".format(x))df

http://img2.58codes.com/2024/20122335Xk8eT6GBnl.jpg

用了decimal模组后,确认程式中的浮点数和我们四捨五入的结果是一致的。
接下来可以放心的计算比例成绩和总成绩了。

df['资审比例成绩'] = (df['资审四捨五入成绩'] * 50/100).apply(lambda x: Decimal(str(x)).quantize(Decimal('.00'), ROUND_HALF_UP))df['面试比例成绩'] = (df['面试四捨五入成绩'] * 50/100).apply(lambda x: Decimal(str(x)).quantize(Decimal('.00'), ROUND_HALF_UP))df['总成绩'] = df['资审比例成绩'] + df['面试比例成绩']df

http://img2.58codes.com/2024/20122335cg7OF4OM3B.jpg

最后的结果就是我们要的四捨五入的总成绩。


关于作者: 网站小编

码农网专注IT技术教程资源分享平台,学习资源下载网站,58码农网包含计算机技术、网站程序源码下载、编程技术论坛、互联网资源下载等产品服务,提供原创、优质、完整内容的专业码农交流分享平台。

热门文章