以实战学习pandas使用方式:统计考生成绩统计及分布

文章介绍了如何利用pandas库读取Excel文件,进行数据统计,包括计算平均分、及格率和优秀率,按班级划分数据,统计各科目比率,并进行排名和名次分布的分析。通过实战操作,强调了pandas在数据处理中的应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

引子

老顾日常工作,是用不到 python 的,所以,老顾的 python 学习进度推进的非常缓慢,至今没用上 pandas 和 numpy,即便参加了新星计划艾派森的学习小组,也没什么动力去看这方面的内容。

结果,昨天在群里,有个小伙伴问老顾能不能帮忙做个数据统计。由于老顾最近准备开营做一期数据库进阶查询的内容,所以这个小伙伴就问怎么用数据库做。

然后的然后,发现这个小伙伴是学了一些 python 基础的。。。。。好么,放着 pandas 不用,想要装个 sqlserver 。。。。也是够可以的。

于是,老顾就用这个小伙伴的内容,做了一次学习,熟悉一下 pandas。

CSDN 文盲老顾的博客https://blog.csdn.net/superwfei

需求

在这里插入图片描述
首先,是有这么一个 excel 表,记录了某年级全部学生的考试成绩。

然后,需要得到全部学生各科的平均分,及格率以及优秀率。

其次,将总表按班级分成多个子表,并对每个班级统计各科的平均分,及格率及优秀率。

再然后,出一个统计表,统计各科目中,各班的平均分,合格率,优秀率,并按照一定权重,计算出最后的合计分,并对合计分进行排名。

最后,出一个简单的统计,统计每个班,前n名各有多少人。

嗯。。。。。好么,一看这需求,那 pandas 必须上啊,一个学习 pandas 的好机会。

逐步实现

使用 pandas 读 excel

import pandas as pd
source = r'期中测试成绩汇总.xls'
df = pd.read_excel(source,sheet_name='学生总成绩')

为了以后使用方便,把文件名单独放到变量中,后续使用就方便一点。

然后,pandas 自带读 excel 文件的方法,并且可以指定 sheet。很方便哦。

初始化一些数据

对于平均分,我们好弄,但是及格率和优秀率,却需要一些数据支持了。经过与小伙伴的沟通,初始了两个字典。

# 初始化常数,满分和统计比率
full = {'语文':120,'数学':120,'英语':120,'物理':70,'政治':70,'化学':50,'历史':50,'总分':600}
grade = {'及格':60,'优秀':80}

用full来记录各科目的满分成绩,用 grade 来记录各档次为满分的百分之多少。

获取 excel 列名

为了保证数据的一致性,我们要读一次 excel 列名,在之后附加数据的时候,保证各列的顺序不会发生紊乱。

# 获取列名
columns = [k for k,d in df.iteritems()]

pandas 自己提供了 iteritems 方法,这就是一个迭代推导式,直接遍历即可。

获取总表的统计数据

# 平均分
print(['','平均分'] + [round(v,2) for v in df.mean()])
# 各种率
print([['',g + '率'] + [round(len(df[df[k] >= full[k] * grade[g] / 100]) / len(df) * 100,2) for k,d in df.iteritems() if k in full] for g in grade])

在这里插入图片描述
可以看到平均分很方便,直接 mean 即可。。。。。

而各种率,老顾就用推导式直接弄了,推导式的学习,可以参考老顾的文章《python 基础系列篇:八、熟练掌握推导式》。

计算方式也很简单,使用 pandas 自带的筛选功能 pd[pd[列] 条件] 可以得到符合条件的结果集,用 len 测下长度,比上总数,就是各种率了。

这里的条件,就是用各科满分成上各种率的比例,为了避免出错,还要限定列是出现在各科目字典中的。

总之,用推导式就完事。

最后把这几个数据,也转成 DataFrame。

# 获取总平均分,总及格率,总优秀率
app = pd.DataFrame([[],[]] + [['','平均分'] + [round(v,2) for v in df.mean()]] + [['',g + '率'] + [round(len(df[df[k] >= full[k] * grade[g] / 100]) / len(df) * 100,2) for k,d in df.iteritems() if k in full] for g in grade],columns=columns)

分班级数据

后边的数据,要分成各个班级,做成子表,所以,先获取下班级信息。集合加排序,很方便。

# 获取班级号
clss = sorted(set(df['班级']))

需要注意变量名不要使用关键字,比如 class 或者 cls 之类的,会报语法错误哦。

得到班级号之后,直接用列表推导式,得到各班级各自的成绩即可。还是用 DataFrame 的筛选功能。

# 获得各班成绩
班级成绩 = [df.loc[df['班级'] == k] for k in clss]

变量名可以用中文哦,实在不知道怎么给变量起名,作为起名废,那就直接上中文。

然后按照总表得到的统计方式,统计各班的统计信息。

# 获得各班统计
班级统计 = [pd.DataFrame([[],[]] + [['','平均分'] + [round(v,2) for v in 班级成绩[i].mean()]] + [['',g + '率'] + [round(len(班级成绩[i][班级成绩[i][k] >= full[k] * grade[g] / 100]) / len(班级成绩[i]) * 100,2) for k,d in 班级成绩[i].iteritems() if k in full] for g in grade],columns=columns) for i,k in enumerate(clss)]

推导式玩得转,代码就看着很简略。

各科目比率统计

再次沟通后得到各比率的权重和列名集合,继续用推导式得到结果。

# 四率计算
四率列名 = ['班级','平均分','折合','及格率','折合','优秀率','折合','巩固率','折合','合计分','名次']

四率 = [[[k,班级统计[i].loc[2][科目],round(班级统计[i].loc[2][科目] * .2,2),班级统计[i].loc[3][科目],round(班级统计[i].loc[3][科目] * .5,2),班级统计[i].loc[4][科目],round(班级统计[i].loc[4][科目] * .1,2),100,10,round(班级统计[i].loc[2][科目] * .2 + 班级统计[i].loc[3][科目] * .5 + 班级统计[i].loc[4][科目] * .1 + 10,2),0] for i,k in enumerate(clss)] for 科目 in full]

名次项,小伙伴有特殊需求,需要1班和2班比较,3,4,5,6,7班进行比较,得出各自的排名。所以,这个只能用循环做了。

final = []
for i,k in enumerate(full):
    arr = 四率[i]
    rank1 = sorted(set([v[9] for u,v in enumerate(arr) if u < 2]),reverse=True)
    rank2 = sorted(set([v[9] for u,v in enumerate(arr) if u > 1]),reverse=True)
    for u,j in enumerate(arr):
        j[10] = (rank1 if u < 2 else rank2).index(j[9]) + 1
    final += [[k,*['' for _ in range(10)]],四率列名] + arr + [[''] * 11]
四率表 = pd.DataFrame(final,columns = 四率列名)      

得出两个排名,然后根据班级序号,更新到四率信息中。最后也转成 DataFrame。

在这里插入图片描述

统计名次分布

这次,是先建立一个 DataFrame,然后,再对各单元格数据进行更新

# 名次分布
分布 = pd.DataFrame([[c,*[0 for _ in range(10)]] for c in clss],columns=['班级',*['前{}名'.format(i * 10) for i in range(1,11)]])
for i in range(1,11):
    tmp = df[['班级','校排名']][df['校排名']<=i * 10].groupby('班级').count()
    for k,j in tmp.iteritems():
        d = dict(tmp[k])
        for u in d:
            print(d[u])
            分布.iloc[clss.index(u),i] = d[u]

写入文件

最后,就是写入到新的 excel 里了,指定另一个文件名,用来写入。

target = r'成绩统计.xls'
f = pd.ExcelWriter(target)
# 将统计信息追加到各表,写文件
final = df.append(app)
final.to_excel(f,sheet_name='学生总成绩', index=False)
for i,k in enumerate(clss):
    班级 = 班级成绩[i].append(班级统计[i])
    班级.to_excel(f,sheet_name=k, index=False)
# 四率写入
四率表.to_excel(f,sheet_name='四率',index=False)
# 分布写入
分布.to_excel(f,sheet_name='分布',index=False)
# 写入结束
f.close()

很好,打完收工。

小结

实战,才是学习最快的途径,碰到问题,分析问题,解决问题,一套流程下来,工具就能理解的七七八八了。

本次给小伙伴帮忙,算是大体上了解了 pandas 的 dataframe 对象,比如自带的聚合函数,比如可以按列筛选,比如 追加数据,比如 loc 与 iloc 的区别。

总之,多学多用,才能掌握的更好,小伙伴们,一起努力吧。

在这里插入图片描述

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

文盲老顾

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值