这学期我们每个人需要填写三张学年鉴定表,每一张表中都有学业总平均分和考试课平均分两项内容,如果想用手工的方式算出这两项内容不知道要花多久,所以我建议编写一个算法(Excel 的函数啥的本质上也是算法)计算这两项内容,下面我就以我的成绩为例讲一下用 Python 算出这两项内容的步骤。
概述
![45662302abe41d15c85b79400b2a8f61.png](https://i-blog.csdnimg.cn/blog_migrate/2f3d7713cafbf2caca78bbcf98823e36.jpeg)
我们打开学校的教务系统,如图所示。
![45c164967c84459c567afbf59bd6a88b.png](https://i-blog.csdnimg.cn/blog_migrate/f56139bd41dba7d02a08a8841558af88.jpeg)
点击成绩查询,如图所示。
![a5d4ec14ff14662239c274d466abbc14.png](https://i-blog.csdnimg.cn/blog_migrate/a8cd76a24be9c4d0de24aa956f1e6a73.jpeg)
随后选择某一学年,然后点击按学年查询,如图所示。
![47dd688ff6d7ac74b4115ebf30f3be05.png](https://i-blog.csdnimg.cn/blog_migrate/c06b309283232f86721a17744ab98e9a.jpeg)
我们可以发现这里只有成绩,没有考核方式,而且里面有非法数据,比如所谓的“合格”。我们暂时先不处理这些非法数据,先找到考核方式在哪里,如图所示。
![7981458b08cfa1950998a2d842376ddf.png](https://i-blog.csdnimg.cn/blog_migrate/89e22a1d608097c1d2d527f4a2e07e30.jpeg)
点击培养计划,如图所示。
![ac69de89c09b559a9dacb23a87630b4f.png](https://i-blog.csdnimg.cn/blog_migrate/805bce5862ee2ae719eba6d8d13a8a3b.jpeg)
这样就可以看到考核方式了,然后把建议修读学期改成全部,其他不变,如图所示。
![fd78cdb579d6a1e648b4a33c61e84475.png](https://i-blog.csdnimg.cn/blog_migrate/76edc0f28b1b8abe8516e91f06b9943a.jpeg)
可以发现它默认是分页显示,每页显示 10 条数据,然而我们需要一页显示所有数据。我这边总共 59 条数据,每页显示 10 条数据,那么我们直接把每页显示的数据条数改成大于等于 59 不就可以了吗?在这里我改成 60,如图所示。
![abeb69f1d28caf55743179c065363f48.png](https://i-blog.csdnimg.cn/blog_migrate/308f91f728132a0287437eef452f9db6.jpeg)
既然数据找到了,那么算法实现起来就简单了,根据课程代码(如果课程名称唯一,也可以根据课程名称,我是根据课程名称进行合并的)把每一学年的成绩和考核方式合并到一张表中。
新建项目
![45662302abe41d15c85b79400b2a8f61.png](https://i-blog.csdnimg.cn/blog_migrate/2f3d7713cafbf2caca78bbcf98823e36.jpeg)
我们用 PyCharm 新建一个 Scientific 项目,项目名称和目录随便(因为是对成绩进行分类汇总,所以我就把项目叫做 GradeSummary),如图所示。
![89937d9e9498dfa108f4ddab6775c72a.png](https://i-blog.csdnimg.cn/blog_migrate/252962be22e2171ab8c719bd3ceec690.jpeg)
点击 CREATE,等待片刻后如图所示。
![1cf6839e6bb9ef5d575940d08185429b.png](https://i-blog.csdnimg.cn/blog_migrate/3b0ff4e1b7f542b37b61588774e32eb0.jpeg)
接下来在 data 目录里面新建两个 Excel 文件,名称如图所示。
![e7cf929e30ce4e454becb58dfeaacafb.png](https://i-blog.csdnimg.cn/blog_migrate/a36a2183b309a294ca34ec33b8b4cf95.jpeg)
然后打开名为成绩统计.xlsx,在里面创建三个 sheet,如图所示。
![4a3a9185de83867bc7c3207a4241b1fd.png](https://i-blog.csdnimg.cn/blog_migrate/89e0df0332a8925fb3ecbd6e5673a671.jpeg)
接着去教务系统成绩查询页,把第一学年的成绩数据放到第一个 sheet,第二学年的放到第二个 sheet,第三学年的放到第三个 sheet,如图所示。
![d81f7a7fbe40ea61f375373afbfcacb9.png](https://i-blog.csdnimg.cn/blog_migrate/9e8d913ee256d9c009311bbf0e5245f0.jpeg)
如果和上图的格式差不多就可以保存关闭,打开考核方式统计.xlsx,去教务系统把考核方式数据复制到这个 workbook 的第一张工作表中,如图所示。
![11f7dc81dd8c51aeafaf6e0f9b191063.png](https://i-blog.csdnimg.cn/blog_migrate/bcebb172b8c20860b58b9fa95cd258e3.jpeg)
如果格式和上图格式差不多就可以保存关闭了。
算法实现
![45662302abe41d15c85b79400b2a8f61.png](https://i-blog.csdnimg.cn/blog_migrate/2f3d7713cafbf2caca78bbcf98823e36.jpeg)
算法的实现过程比较简单,分为以下几步:载入成绩,载入考核方式,合并,处理,计算总平均分,计算考试科平均分。(过程的顺序不唯一,比如载入成绩和载入考核方式可以互换)。
下面就可以搭建一个框架了,代码如下:
class
01
初始化
在其中我们需要三个数据集列表,一个是存放成绩数据,一个是存放考核方式数据,还有一个是存放合并后的数据。每个列表中有三个元素(第几个元素就对应第几学年)。另外我们还需要一个学年的序列,因为要算每一学年的学业总平均分和考试课平均分。知道这些写出构造方法就是轻而易举了,代码如下:
def
02
载入成绩
载入成绩的实现很简单,读取成绩统计.xlsx,顺序遍历三个 sheet,在第一次遍历过程中把课程名称的数据放到 self.dataset_list1[0]['课程名称']里面,第二次遍历过程中把课程名称的数据放到 self.dataset_list1[1]['课程名称']里面,以此类推。
在每次遍历的过程中仅仅载入一个课程名称有点说不过去,我们还需要把成绩载入一下,成绩就是考试成绩,补考成绩,重修成绩三个中取最大值。在这里要处理的问题有点多,下面我们来一一解决一下。
第一个问题,如果成绩,补考成绩,重修成绩对应的数据类型不一样,比如我,没有补考和重修,补考成绩和重修成绩对应的数据类型是字符串,怎么办?这个问题解决起来很简单,只要把补考成绩和重修成绩修改成 0 就行了,这样就可以进行比较,而且结果没有错误。
第二个问题,像“合格”这样的数据怎么办?最终我们是选择忽略掉这种数据,但是我们现在不忽略,直接令成绩为空字符串。
知道了这些代码实现就简单了,代码如下:
def
03
载入考核方式
载入考核方式的实现很简单,读取考核方式统计.xlsx,获取课程名称,考核方式,建议修读学期这三条数据,然后根据建议修读学期计算对应的学年,最后根据学年计算出索引,下面我就讲一下如何计算。
如果建议修读学期是 1 或者 2,那么对应第 1 学年;如果建议修读学期是 3 或者 4,那么对应第 2 学年;以此类推。我们可以发现:(建议修读学期[i]-1)//2+1 就是第几学年,所以索引 = (建议修读学期[i]-1)//2+1-1 = (建议修读学期[i]-1)//2。因为我总共只有 3 个学年,所以索引必须小于等于 2!
最后把数据存放到对应的容器中就行了,代码如下:
def
04
合并
合并的实现很简单,把成绩数据集列表(self.dataset_list1)中第 i 个数据集和考核方式数据集列表(self.dataset_list2)中第 i 个数据集按照课程名称合并到 self.dataset_list[i] 中,其中 0 <= i <= 2。合并完成之后删除成绩数据集列表和考核方式数据集列表,代码如下:
def
05
处理
处理的实现很简单,如果成绩是数,保留该数据。在这里我使用一个临时的数据集列表保留筛选后的数据,最后把临时的数据集列表赋值给 self.dataset_list,代码如下:
def
06
计算总平均分
计算总平均分很简单,课程成绩总和除以课程数目,不要忘了一学年一学年的计算,代码如下:
def
07
计算考试科平均分
最后是计算考试课平均分,也就是在学业总平均分的基础上多了一步筛选操作——筛选出考试课,代码如下:
def
最后我直接给出完整代码:
from
运行结果如图所示。
![2e536ca28f08afd929745b193be48c56.png](https://i-blog.csdnimg.cn/blog_migrate/e22fc7fad5133200b6023724a76f510e.jpeg)