在高中阶段,学生考试成绩的分析是一个重要的而频繁的应用场景,快速、有效、精准的生成学生成绩的分析报告,是学情监控和开展个性化教学的前提。这个问题是基础性问题,实现的方法非常多,主要是基于Excel。在这里用python的pandas做一遍,体会一下办公自动化的乐趣。这篇文章以高中学生的成绩分析为背景,使用pandas(是一个基于numpy的python的数据分析包)对学生成绩进行分析。本文分为如下部分:

1、全校成绩表的生成(虚构);

2、年级成绩分析;

3、班级成绩分析;

4、学科成绩分析;

5、总结与思考。

学生成绩分析是本文的场景,写这篇文章的目的是总结我参加华为云大数据挑战赛时对于pandas的学习体会,供大家参考,本文的源码地址:https://github.com/Fire2341/Learning_Summary。

在开始之前,导入numpy和pandas,按照习惯写成如下形式。如果没有这个模块,还是老规矩,使用pip install numpy和pip install pandas安装一下。

import numpy as npimport pandas as pd

一、全校成绩表的生成(虚构)

在开始之前,先生成我们的分析对象,学生成绩表,假设本次考试为理科班的摸底考试。学生成绩表包括:

  1. 基本信息,包括:学生姓名、学生年级、学生班级;

  2. 学生成绩,假设学生的成绩服从正态分布,生成的成绩包括如下科目:语文(150分)、数学(150分)、英语(150)、物理(100分)、化学(100分)、生物(100分),并计算总分。

生成的表格流程如下:先确定每个年级的班级数目,并随机生成各班人数(55-68人之间),由此计算得到全校人数。根据全校人数随机生成学生姓名,并在确定各科平均值和标准差后,根据正态分布规律随机生成各个学生的各科成绩,并计算每位学生的总分,以此获得一份总的成绩汇总表,主要代码如下。由于这部分代码较为冗长且不是主要部分,感兴趣的朋友可以点击源码查看。

class_name, student_num = generate_class() # 生成班级信息all_num = students_sum(student_num) # 生成全校学生总数student_name_group = generate_student_name(all_num) # 生成全校学生名字student_info = init_table(class_name, student_num, student_name_group) # 将年级、班级、学生信息初始化到表格中student_list = get_list(all_num, student_info) #生成成绩汇总表student_list.to_excel('学生成绩表2.xlsx') # 保存成绩表

取数据表的前5个来看,还真像那么回事(所有名字和成绩数据均为python随机生成,如有雷同,纯属巧合)。在生成的成绩表中,一共有3个年级,其中高一26个班,高二27个班,高三个23班,各班学生人数介于55-68人之间,全校一共4619名学生。

为了展现pandas的相较于excel的优越性,在下面的分析中,各部分使用的代码尽量不超过5行。

二、年级分析

2.1 各年级的最低分、最高分、平均分和中位数

为了直观的反映各年级的整体教学情况,在这里计算各年级的各科最高分、最低分、平均分和中位数。在这一部分用到的函数主要是.groupby和.agg。groupby可以按年级分组,.agg能够对各年级各分组应用各个函数(求最大值、最小值、平均值、中位数)进行计算。

subject_name = ['语文','数学','英语','物理','化学','生物','总分']grade_analysis = student_list.groupby('年级')[subject_name].agg(['max','min','mean','median']).reset_index()grade_analysis.head()

从结果来看,这份随机生成的成绩表,各个科目的都有人考满分,不符合实际情况,但是符合我的正态分布规律了……

2.2 获取各年级的成绩前5的学生

不管哪个层级的学校,拔尖学生都在学校人才培养工作占有重要地位,而学习成绩可以在一个侧面反映拔尖学生的范围。在这里筛选各年级成绩排名前5的学生。这一部分用到的函数主要是.groupby和.sortvalues。使用.groupby的.rank()获取年级排名,使用.sortvalues按照年级和总分进行分组,使用.groupby的.get_group('高三')获得高三学生的年级排名,在这里展示高三前五名的情况。

student_list['年级排名'] = student_list['总分'].groupby(student_list['年级']).rank(ascending=False).astype(int)student_list.sort_values(['年级','总分'], ascending=False, inplace=True)student_list.groupby('年级').get_group('高三').head()

第1名真是天选之子,随机生成的成绩都能有3科拿满分。

与获取年级倒数前5的方法一样,把.sort_values()的ascending参数(是否升序)改为True就可以。

student_list.sort_values(['年级','总分'], ascending=True, inplace=True)student_list.groupby('年级').get_group('高三').head()

2.3 数据保存

数据保存是一个重要的环节,毕竟学校的成绩分析报告是要打印出来发给各个年级主任、班主任的。使用.to_excel()导出到excel中,在这里导出整体情况,以及各个年级的前五和倒数前五的情况。

grade_excel = pd.ExcelWriter(r'年级分析.xlsx')grade_analysis.to_excel(grade_excel, sheet_name='整体情况')grade_name = ['高一','高二','高三']student_list.sort_values(['年级','总分'], ascending=False, inplace=True)for name in grade_name:    student_list.groupby('年级').get_group(name).head().to_excel(grade_excel, sheet_name=name+'-前五')student_list.sort_values(['年级','总分'], ascending=True, inplace=True)for name in grade_name:    student_list.sort_values(['年级','总分'], ascending=False, inplace=True)    student_list.groupby('年级').get_group(name).head().to_excel(grade_excel, sheet_name=name+'-倒数前五')grade_excel.save()

导出的效果还是不错的。

3 班级分析

3.1 班级整体情况分析

分析各班第1在年级的位置,能够帮助学校在整体层面把握各班的教学质量。在班级排名的获取方法与获取年级排名的方法一致,对数据表“总分”这一列用“班级”这一列取groupby,然后对每个groupby进行rank()计算。

student_list['班级排名'] = student_list['总分'].groupby(student_list['班级']).rank(ascending=False).astype(int)student_list[student_list['班级排名'] == 1].groupby('年级').get_group('高三')

从下表可以看出,有个班级有两位同学拿了年级前10,真是天选之班。

使用如下代码,进一步分析是哪个班。

student_list.sort_values(['年级排名'],ascending=True,inplace=True)student_list.groupby('年级').get_group('高三').head(10).groupby(['班级'])['年级排名'].count()

原来天选之班不仅仅只有一个……

3.2 各班一本率及学科成绩分析

一本率可以说是高中班级中的重要数据了,以广西2019年高考理科一本线(509分)为标准,计算各班一本率。在对各班进行groupby的基础上,使用一个apply函数计算各班过一本线的人数,进而计算一本率。与年级整体数据的分析方法类似,按班级分析各科成绩的最高分、最低分、平均分、中位数,使用.merge()函数(相当于Excel中的vlookup函数)将各班各科的数据与前面的一本率数据匹配,最后按照一本线降序呈现数据。

class_list = pd.DataFrame()class_list['一本人数'] = student_list.groupby('班级')['总分'].apply(lambda x: np.sum((x >=510).astype(int)))class_list['班级人数'] = student_numclass_list['一本率'] = class_list['一本人数']/class_list['班级人数']subject_name = ['语文','数学','英语','物理','化学','生物','总分','年级排名']class_list = class_list.merge(student_list.groupby('班级')[subject_name].agg(['max','min','mean','median']).reset_index(), on='班级', how='left')class_list.head()

从图中可以看出,全校一本率最高的班级是1704班,但是一本率仅有36.2%,看来这个虚构的学校成绩并不好……

3.3 数据保存

按照类似与年级数据的保存方法,保存班级分析的数据。

class_excel = pd.ExcelWriter(r'班级分析.xlsx')class_list.to_excel(class_excel, sheet_name='整体情况')for name in grade_name:    student_list[student_list['班级排名'] == 1].groupby('年级').get_group(name).to_excel(class_excel, sheet_name=name)class_excel.save()

4 学科分析

4.1 分数段分析

对于各个学科,比较重要的数据是各个年级、各个分数段的人数情况。使用的方法pd.cut()函数,对各个学科的各个分数段进行切割,并且保存为DataFrame(本文所有数据均为此格式)。由于在这个分析中有按照年级的循环求解,所以直接在开头就定义写入excel的subjectexcel对象,在循环结尾直接.toexcel()保存。

subject_excel = pd.ExcelWriter(r'学科分析.xlsx')bins = [0,40,60,80,100,120,140,150]group_name = ['高一','高二','高三']subject_name = ['语文','数学','英语','物理','化学','生物']for name in group_name:    grade = student_list.groupby('年级').get_group(name)    df = pd.DataFrame()    for s_name in subject_name:        cuts = pd.cut(grade[s_name],bins=bins) #可选label添加自定义标签        subject_cut = grade.groupby(cuts)[s_name].count()        df[s_name] = subject_cut    df.index.name = name    df.to_excel(subject_excel, sheet_name=name+'成绩分布')df

从成绩区间可以看出,成绩主要分布在平均数附近,是很符合正态分布了。想起在前面分析年级倒数的时候有个学生生物81分,但是年级排名倒数第3,是很偏科了。

4.2 偏科学生分析

偏科学生在某些学科是潜力股,发现偏科学生在某种意义上是发现“好苗子”的过程。在本次成绩表中,假定数学成绩大于130且语文和英语成绩小于90分的学生为偏科学生。先构建一个'数学偏科'的flag,然后进行筛选。在这一部分的最后,把学科分析部分的数据保存到excel中。

student_list['数学偏科'] = ((student_list['数学']>=130) & (student_list['语文']<90) & (student_list['英语']<90)).astype(int)partial = student_list[student_list['数学偏科'] == 1]partial.drop(['数学偏科'],axis=1,inplace=True)partial.to_excel(subject_excel, sheet_name='偏科学生')subject_excel.save()partial.head()

图中的晋启同学数学考了149,其他学科都不超过80,是很偏科了。

使用如下代码,看看各个年级有多少人是数学偏科的。可以看到,高二年级的偏科人数最多。

partial.groupby('年级')['姓名'].count()

五、思考

代码和文章写到这里已经写了 6个多小时了,需要写一个结尾总结一下收获,减轻一下不务正业,没有读文献的负罪感。有人说这些事情用Excel完全可以办到,为什么要在这里写代码呢?全文中使用到的方法,函数均为我在做一个大数据比赛时学到的函数,换一个场景使用证明我学会了;其次,那个比赛需要处理的数据量是1.47亿条,用Excel打不开(T_T),所以写代码也是适用于大规模的数据处理;另外,代码具有复用性,只要使用场景不变,数据格式不变,可以说是一劳永逸的,适合于重复机械的工作场景。比如高中学生考试,有周测、月考、段考、期末考、摸底考……,而跑一次代码就可以生成成绩报告,为啥还要每次重复操作Excel呢?

附录

这篇文章主要用到如下方法:

  1. .groupby()系列方法,包括.groupby().agg(), .groupby().apply(), .groupby().get_group()等,用以实现分年级、分班级计算;

  2. pd.readexcel(), pd.toexcel(),Excel的读取与存储;

  3. pd.merge(),数据筛选,相当于Excel中的vlookup;

  4. df.sort_values(),对数据进行排序;

  5. df.drop(),按条件去除某行或某列;

  6. df.cut(),给定区间,分析数据所属区间;

  7. df.count(),分析某列数据各个元素的值,结合.groupby可以实现Excel的数据透视表效果。

其他方法(未在此场景中应用):

  1. np.unique(), 去除numpy的重复值,df.drop_duplicates(),按条件去除DataFrame的重复值;

  2. pd.todatetime(),将其他类型的时间数据转换为时间戳,df.dt.totalseconds(),把时间数据转化为秒;

  3. df.diff(1),计算某两列的差值(一般是计算dt时间内变量的变化量)

  4. df.shift(),向上或向下移动某列数据;

  5. df.fillna(),缺失值填充;

  6. .loc[],按当前索引提取某行;.iloc[],按数字提取某行;

  7. .isin(),分析某列元素是否在另一数组中。

源码链接:https://github.com/Fire2341/Learning_Summary

python groupby_用python自动生成全校学生成绩报告相关推荐

  1. python list转字符串_我用python写了个自动生成给文档生成索引的脚本!懒人智慧...

    我用 python 写了一个自动生成索引的脚本 简介:为了刷算法题,建了一个 GitHub仓库: PiperLiu / ACMOI_Journey ,记录自己的刷题轨迹,并总结一下方法.心得.想到一个 ...

  2. python图书馆管理系统实验报告_基于Python的图书馆业务报表自动生成研究

    龙源期刊网 http://www.qikan.com.cn 基于 Python 的图书馆业务报表自动生成研 究 作者:辛海滨 来源:<电脑知识与技术> 2016 年第 27 期 摘要:针对 ...

  3. 「懒惰的美德」我用 python 写了个自动生成给文档生成索引的脚本

    我用 python 写了一个自动生成索引的脚本 简介:为了刷算法题,建了一个 GitHub仓库:PiperLiu / ACMOI_Journey,记录自己的刷题轨迹,并总结一下方法.心得.想到一个需求 ...

  4. Python 自动化教程(5) : 自动生成Word文件

    系列教程: Python 自动化教程(1) 概述,第一篇 Excel自动化 Python 自动化教程(2) : Excel自动化:使用pandas库 Python 自动化教程(3) : 自动生成PPT ...

  5. Python 自动化教程(4) : 自动生成PPT文件 Part 2 (干货)

    系列教程: Python 自动化教程(1) 概述,第一篇 Excel自动化 Python 自动化教程(2) : Excel自动化:使用pandas库 Python 自动化教程(3) : 自动生成PPT ...

  6. 【定制开发】【M11】Python采集数据源,自动生成Excel报表:避免人力浪费,提高工作效率

    目录 一.背景 二.采集数据源 2.采集[氮氨]数据 3.采集[COD 化学需氧量]数据 4.采集[总氮]数据 三.输出Excel内容样式 1.输出文件命名格式 2.文件内容格式详述 四.解决方案 1 ...

  7. python学习之路—自动生成唯一标识(md5加密方式)

    前言 在python存入数据库时,如果数据库的主键不是自增方式,那么我们可能需要自己生成一个唯一标识符,现在最好的方法就是md5加密生成的32位作为主键,本文将会介绍python的两种自动生成唯一标识 ...

  8. Python创建文件时自动生成文件信息

    Python创建文件时自动生成文件信息 在创建python脚本文件时,对文件初始化自动生成一些文件信息来进行设置 1 打开路径 2 调整面板 3 面板填写样式 参考链接 Pycharm创建文件时自动生 ...

  9. python自动化代码生成_python 自动生成C++代码 (代码生成器)

    Python代码自动生成方法(代码生成器)遇到这种事在工作遇到问题,你需要写很多c++基础数据库类,但这些类是一样的,只不过是添加,删除,修改并检查.如果你手动编写代码,它是费力而容易出错;它可以很容 ...

最新文章

  1. 弹出框的鼠标拖拽事件
  2. Actuator 端点监控
  3. 京瓷打印机几个常见密码
  4. Angular中父组件通过ViewChild调用子组件的方法
  5. CVPR 2022 | 华为诺亚北大提出量子启发MLP,性能超越Swin Transfomer
  6. java 做ui_【原创】JavaApplication的UI也可以做的很美
  7. cogs 167. [USACO Mar07] 月度花费
  8. BaseAdapter的ArrayIndexOutOfBoundsException
  9. sqlite3 cmd命令输出乱码
  10. 插头DP题目泛做(为了对应WYD的课件)
  11. 也谈压缩感知(compressive sensing)
  12. win—命令行窗口一层一层的打开文件
  13. 【HighCharts系列教程】一、认识Highcharts
  14. .Net中消除Dll中的dependency
  15. Unicode-GBK映射表下载。
  16. STM32电机TB6612驱动
  17. 台式计算机键盘驱动,台式电脑键盘无法找到驱动, 为什么?
  18. 如何快速给多张图片添加边框,这招你一定要会
  19. Microsoft SQL Server 生成随机数字、字符串、日期、验证码以及 UUID
  20. js 下载 download

热门文章

  1. VMware 设置网络
  2. python之路_前端基础之jQuery入门2
  3. [轉]Exploit Linux Kernel Slub Overflow
  4. 3-算法 鸡兔同笼 简单逻辑
  5. 鸿蒙hms在哪儿更新,原创 华为鸿蒙系统已开始实施!华为EMUI10.1再更新:HMS将决定战略方向...
  6. java moneyutils_java中每月等额与先息后本计算
  7. Html前端基础(form表单、img标签、a href标签、id的作用)
  8. 吃豆人动态模型创建---canvas
  9. html 自动生产,【SQL】用Sql Server自动生产html格式的数据字典
  10. python代码中怎么增加数据_python 实现数据库中数据添加、查询与更新的示例代码...