Python实现学生成绩分析

本文介绍了一个生成12个月份10名同学成绩的随机数程序,并展示了如何统计分析各科平均分、总分、月考表现以及学生个人成绩年变化。通过实例演示了数据可视化,如月考平均分占比图和学生科目成绩曲线。

第一步 生成月考成绩表
第二步 生成学生成绩总表
第三步 数据分析
第三步 数据呈现
第四步 自动生成word报告

"""
实现生成12个月份10名同学成绩的随机数
"""
import random
from openpyxl import Workbook

#新建空表
#写二月份到十二月份数据
filenum = 12 #文件数
head = ["姓名","语文","数学","英语","地理","生物","物理","化学"]



name = []
grad = []
all_name = []
nber = 11 #人数
p = 1

xing = ['赵', '钱', '孙', '李', '周', '吴', '郑', '王', '冯', '陈', '褚', '卫', '蒋', '沈', '韩', '杨']
ming = ['明','刚','红','越','芳','花','颖','鹏','柯','心','航','睿']
#把名字写入文件
def writename(number):
	for i in range(1,number):
		name = xing[random.randint(0,len(xing)-1)]+ming[random.randint(0,len(ming)-1)]
		#ws.cell(row=i+1,column=1).value = name
		all_name.append(name)
	return all_name

#把分数写入文件
def writescore(number):
	for i in range(1,number):
		for j in range(2,len(head)+1):
			grad = random.randint(int(random.gauss(65,6)),100)
			ws.cell(row=i+1,column=j).value = int(grad)


#存储数据,写入文件
def savedata(sheet,lsts):
	for i in range(1,len(lsts)+1):
		ws.cell(row=i+1,column=1).value = lsts[i-1]
		

#批量写文件
for i in range(1,filenum+1):
	wb = Workbook()
	ws = wb.active	
	#生成表名和表头
	ws.title = str(i)+"月份成绩"
	ws.append(head)
	if p == 1: 
		wname = writename(nber)
		p = 0
	print(wname)
	savedata(ws,wname)
	writescore(nber)
	wb.save("./crtdata/"+str(i)+"月份成绩表.xlsx")
#获取输入字符串所在行的数据
from openpyxl import Workbook
from openpyxl import load_workbook

import numpy as np
import os
import matplotlib.pyplot as plt
plt.rcParams['font.sans-serif'] = ['Arial Unicode MS']

filepath = "/Users/hangyang/Documents/python_work/crtdata/"
dirs = os.listdir(filepath)

filepath1 = "/Users/hangyang/Documents/python_work/学生情况1/"

filepath2 = "/Users/hangyang/Documents/python_work/学生情况2/"

filepath3 = "/Users/hangyang/Documents/python_work/学生成绩/"

head = ["姓名","语文","数学","英语","地理","生物","物理","化学"]
pie_head = ["语文","数学","英语","地理","生物","物理","化学"]
pie_month = ["1月份","2月份","3月份","4月份","5月份","6月份","7月份","8月份","9月份","10月份","11月份","12月份"]

#获取相同信息所在行数据
def getsameinfo(sheet,st1,rows,cols):
	lst = []
	for i in range(1,rows+1):
		for j in range(1,cols+1):
			if str(sheet.cell(row=i,column=j).value) == st1:
				for k in range(j,cols+1):
					cel = sheet.cell(row=i,column=k).value
					lst.append(cel)
				return lst

#获取相同信息所在列数据
def getsamecolumninfo(sheet,st1,rows,cols):
	lst = []
	for i in range(1,rows+1):
		for j in range(1,cols+1):
			if str(sheet.cell(row=i,column=j).value) == st1:
				for k in range(i+1,rows+1):
					cel = sheet.cell(row=k,column=j).value
					lst.append(cel)
				return lst

#存储数据,写入文件
def writedata(sheet,lsts,tmp):
	for data in lsts:
		for j in range(1,len(data)+1):
			sheet.cell(row=tmp,column=j).value = data[j-1]
		tmp=tmp+1
	return tmp

#获取人名
def getstudentname(path,dir):
	wkbk = load_workbook(path+dir[0])
	wkst = wkbk.active
	rows = wkst.max_row
	cols = wkst.max_column
	student = getsamecolumninfo(wkst,"姓名",rows,cols)
	return student

#打开Excel文件,获取相同信息并保存
def deal2save_Excel(filepath,dirs,info):
	lst2 = []
	for d in dirs:
		if d.split(".")[1] in ["xlsx","xls"]:
			wb1 = load_workbook(filepath+d)
			ws1 = wb1.active
			rows = ws1.max_row
			cols = ws1.max_column
			lst1 = getsameinfo(ws1,info,rows,cols)
			lst2.insert(1,lst1)
		elif d in ["DS_Store"]:
			os.remove("DS_Store")
	return lst2

#根据人名创建sheet存储分类后的数据
def classifyasname_single(path,dirs,stu):
	#按学生名新建sheet
	wb = Workbook()
	ws = wb.active	
	ws.append(head)
	#按学生名新建多个空sheet
	for name in stu:
		wb.create_sheet(name)
	wb.remove(wb['Sheet'])
	
	#把学生数据写入sheet
	ID = 0
	tmp = 2
	for i in wb.sheetnames:
		ws = wb[i]
		ws.append(head)
		lst = deal2save_Excel(path,dirs,stu[ID])
		ID = ID+1
		#print("[classifyasname_single函数]:\n",lst)
		tmp = writedata(ws,lst,tmp)
		tmp = 2
		ws.delete_cols(idx=1,amount=1)	
		ws.insert_cols(idx=1,amount=1)
		for h in range(1,ws.max_row):
			ws.cell(h+1,1).value = str(h)+"月"
		ws.cell(1,1).value = "月份"
	wb.save("./学生情况2/"+"学生情况.xlsx")
	wb.close()


#保存数据到Excel表的a行b列
def writesingleval(sheet,val,a,b):
	sheet.cell(row=a,column=b).value = val

#求单科平均分
def getavgscore(wb,ws):
	rows = ws.max_row
	cols = ws.max_column
	l_cols = list(np.arange(2,cols+1,1))
	x = 0
	for col in ws.iter_cols(min_row=2,min_col=2):
		for v in col:
			column_data = [v.value for v in col]
		avg = int(np.average(column_data))
		writesingleval(ws,avg,rows+1,l_cols[x])
		x = x+1
		#print("[countingscore函数求平均分]:\n",column_data,avg,l_cols[x-1])

#求每月总成绩
def getsumscore(wb,ws):
	rows = ws.max_row
	cols = ws.max_column
	l_rows = list(np.arange(2,rows+1,1))
	x = 0
	for row in ws.iter_rows(min_row=2,min_col=2):
		for v in row:
			row_data = [v.value for v in row]
		fsum = int(np.sum(row_data))
		writesingleval(ws,fsum,l_rows[x],cols+1)
		x = x+1
		#print(column_data,avg,l_cols[x-1])
	

#一个文件多个sheet计算平均分及总分
def countingscore_single():
	dirs2 = os.listdir(filepath2)
	for d in dirs2:
		if d.split(".")[1] in ["xlsx","xls"]:
			wb = load_workbook(filepath2+d)
			ws = wb.active
			ws.cell(1,1).value = "月份"
			for i in wb.sheetnames:
				ws = wb[i]
				print(ws)
				getavgscore(wb,ws)
				getsumscore(wb,ws)
				ws.cell(row=ws.max_row,column=1).value = "平均分"
				ws.cell(row=1,column=ws.max_column).value = "月考总分"
				wb.save("./学生成绩/学生成绩总表.xlsx")
			wb.close()
		elif d in [".DS_Store"]:
				print("loading... ",d.split(".")[1] in ["xlsx","xls"])
				os.remove("./学生情况2/.DS_Store")
	

#读取键盘输入


#画图
def studentcase_plot(name,course):
	print ("下面显示"+name+"所学科目"+course+"成绩的年变化曲线 〉〉〉")
	wb = load_workbook(filepath2+"学生情况.xlsx")
	ws = wb.active
	for i in wb.sheetnames:
		if i.split(".")[0] == name:
			ws = wb[i]
			rows = ws.max_row
			cols = ws.max_column
			m_score = getsamecolumninfo(ws,course,rows,cols)
			m_time = getsamecolumninfo(ws,"月份",rows,cols)
			print(name)
			print(m_score)
			print(m_time)
			plt.title(name+course+"成绩年变化曲线",fontsize=24)
			plt.xlabel("月份",fontsize=14)
			plt.ylabel("分数",fontsize=14)
			plt.tick_params(axis='both',labelsize=14)
			plt.bar(m_time,m_score)
			plt.savefig(name+course+"成绩.jpg")
			plt.show()
			plt.close()
		wb.close()

def  classcase_plot(course):
	print ("下面显示所有学生"+course+"年变化曲线 〉〉〉")
	wb = load_workbook(filepath2+"学生情况.xlsx")
	ws = wb.active
	for i in wb.sheetnames:
		ws = wb[i]
		rows = ws.max_row
		cols = ws.max_column
		m_score = getsamecolumninfo(ws,course,rows,cols)
		m_time = getsamecolumninfo(ws,"月份",rows,cols)
		plt.title("全班"+course+"成绩年变化图",fontsize=24)
		plt.xlabel("月份",fontsize=14)
		plt.ylabel("分数",fontsize=14)
		y_ticks = np.arange(-10,110,5)
		plt.yticks(y_ticks)
		plt.scatter(m_time,m_score)
		#plt.plot(m_time,m_score)
		print(ws)
		wb.close()
	plt.savefig(course+"班级成绩.jpg")
	plt.show()
	plt.close()

def monthly_score(monthly):
	wb = load_workbook(filepath+monthly+"成绩表.xlsx")
	ws = wb.active
	rows = ws.max_row
	cols = ws.max_column
	lst = []
	getavgscore(wb,ws)
	ws.cell(row=ws.max_row,column=1).value = "平均分"
	for i in range(2,cols+1):
		cel = ws.cell(row=ws.max_row,column=i).value
		lst.append(cel)
	dic = dict(zip(pie_head,lst))
	print(dic)
	dic_course = [key for key in dic]
	dic_averge = [value for value in dic.values()]
	plt.pie(dic_averge, labels=dic_course, autopct="%1.2f%%")
	plt.title(monthly+"各科成绩平均分占比", fontsize=24)
	plt.savefig(monthly+"各科成绩平均分占比.jpg")
	plt.show()
	wb.close()

def plotpicture(student_name,course_name):
	print("输出学生科目成绩...")
	studentcase_plot(student_name,course_name)
	print("输出班级科目成绩...")
	classcase_plot(course_name)
	print("输出月考总分...")
	monthly_score("1月份")

def countrate(month,course):
	wb = load_workbook(filepath+month+"成绩表.xlsx")
	ws = wb.active
	rows = ws.max_row
	cols = ws.max_column
	lst = getsamecolumninfo(ws,course,rows,cols)
	passnum = 0
	excellencenum = 0
	for j in lst:
		if j >= 60:
			passnum = passnum+1
		if j >= 90:
			excellencenum = excellencenum+1
	passrate = passnum/(rows-1)*100
	excellencerate = excellencenum/(rows-1)*100
	passnum = 0
	excellencenum = 0
	#print("passrate is:",passrate,"%")
	#print("excellencenum is:",excellencerate,"%")
	return [passrate,excellencerate]
		

def writeinfotodoc(month,course,sname):
	from docx import Document
	from docx.shared import Inches
	document = Document()
	document.add_heading('2022年度成绩分析',0)
	document.add_heading('一、全班整体情况分析')
	paragraph = document.add_paragraph('我校初三四班共有学生10人,本年度共进行12次月考,整体情况如下:')
	
	paragraph = document.add_paragraph()
	guide = paragraph.add_run("1、全班各科成绩年变化图")
	guide.style = 'Strong'
	paragraph = document.add_paragraph("显示了全班所有同学所有科目全年的分布图像,可以看出同学成绩主要集中分布的范围。")
	print("输出班级科目成绩...")
	classcase_plot(course)
	pic_shape = document.add_picture(course+'班级成绩.jpg',width=Inches(5.5))
	print("班级科目成绩输出完毕!!!")

	print("输出月考总分...")
	paragraph = document.add_paragraph()
	guide = paragraph.add_run("2、月考总分各科占比")
	guide.style = 'Strong'
	paragraph = document.add_paragraph("显示了各科在月考总分中所占比重,可以看出班级的优势和薄弱科目。")
	print("输出"+month+"各科分数占比...")
	monthly_score(month)
	pic_shape = document.add_picture(month+'各科成绩平均分占比.jpg',width=Inches(5.5))
	print("各科分数占比输出完毕!!!")

	passrate_lst = []
	excellentrate_lst = []	
	paragraph = document.add_paragraph()
	guide = paragraph.add_run("3、"+month+"各科成绩及格率及优秀率情况")
	guide.style = 'Strong'
	for cs in pie_head:
		value1 = float(countrate(month,cs)[0])
		passrate_lst.append(value1)
		value2 = float(countrate(month,cs)[1])
		excellentrate_lst.append(value2)
		paragraph = document.add_paragraph(str(cs)+'及格率(成绩大于60分):'+str(value1)+'%'+'		'+'优秀率(成绩大于90分):'+str(value2)+'%')


	document.add_heading('二、学生个人情况分析')
	paragraph = document.add_paragraph("以下为"+sname+"同学各科成绩年度统计数据")
	print("输出"+sname+"同学科目成绩...")
	for cs in pie_head:
		studentcase_plot(sname,cs)
		pic_shape = document.add_picture(sname+cs+'成绩.jpg',width=Inches(5.5))
	print("学生科目成绩输出完毕!!!")
	#导出Excel中的数据到word

	document.save("班级2022年度成绩分析报告.docx")
	
#主程序
stu = getstudentname(filepath,dirs)
print("create an excel file...saved in multi-sheet")
classifyasname_single(filepath,dirs,stu)
print("begin counting score...status is ok")
countingscore_single() 
#writeinfotodoc("1月份")


print("===========画图===========")
student_name = input("请输入待查询学生姓名:\n");
print ("你输入的内容是: ",student_name)
course_name = input("请输入待查询科目名称:\n");
print ("你输入的内容是: ",course_name)
month_value = input("请输入待查询月份,例如(1月份):\n");
print ("你输入的内容是: ",month_value)

#plotpicture(student_name,course_name)
writeinfotodoc(month_value,course_name,student_name)




本文介绍的是利用Python语言,做成绩分析生成成绩分析动态图表。Python语言可以利用Pandas、Pyecharts等各种类,进行数据分析。 本文介绍的成绩分析大体分为三步: 一、拼合单科成绩,合成学年成绩计算总分,按总分成绩排名次,然后由学年成绩筛选出各个班级的成绩,将学年成绩,各班级成绩存入一个Excel文件中,工作表分别命名为学年成绩,高三(1)班……等 二、利用生成的第一步生成的Excel文件,做成绩分析,保存成绩分析表格。 三、利用成绩分析表格,做成绩分析动态图。 下面是部分源代码: 1、成绩整理与合 import glob import os import pandas as pd from functools import reduce inputPath="./原始成绩/" writer_lk = pd.ExcelWriter('./整理后的成绩/2020一模理科总成绩及各班级成绩.xlsx') writer_wk = pd.ExcelWriter('./整理后的成绩/2020一模文科总成绩及各班级成绩.xlsx') inputWorkbook=glob.glob(os.path.join(inputPath,"*.xls")) #====================读取全部学生的所有科目成绩=================================== yw_score = pd.read_excel(inputWorkbook[2]) sxlk_score = pd.read_excel(inputWorkbook[1]) sxwk_score = pd.read_excel(inputWorkbook[0]) yy_score = pd.read_excel(inputWorkbook[5]) yy_score['英语'] = (yy_score['英语'] * 1.25).round(0)#英语成绩计算听力成绩*1.25 lkzh_score = pd.read_excel(inputWorkbook[4]) wkzh_score = pd.read_excel(inputWorkbook[3]) #======================================================================= #====================整理出理科成绩及分班成绩计算总分、总分排名、班级排名============================= lk_class = ['高三(1)班','高三(2)班','高三(3)班','高三(4)班'] wk_class = ['高三(5)班','高三(6)班'] lk_yw = yw_score.loc[(yw_score.班级.isin(lk_class)), ['班级','姓名','语文']] lk_sx = sxlk_score[['姓名','数学']] lk_yy = yy_score.loc[(yy_score.班级.isin(lk_class)), ['姓名','英语']] lk_k3 = lkzh_score[['姓名','物理','化学','生物','理综']] lk_list = [lk_yw, lk_sx, lk_yy, lk_k3] score_lk = (reduce(lambda left, right: pd.merge(left, right, on='姓名'), lk_list)) score_lk['总分'] = (score_lk['语文'] + score_lk['数学'] + score_lk['英语'] + score_lk['理综']).round(0) def sort_grade(score): score_sort = score.sort_values(by=['总分'], ascending=False) score_sort['年级排名'] = score_sort['总分'].rank(ascending=0,method='min') return score_sort def sort_class_lk(score_garde,name): class_sort = score_garde.loc[score_garde.班级 == name, :] class_sort = class_sort.sort_values(by=['总分'], ascending=False) class_sort['班级排名'] = class_sort['总分'].rank(ascending=0,method='min') class_sort.to_excel(writer_lk, index=None, sheet_name=name) lk_grade_sort = sort_grade(score_lk) lk_grade_sort.to_excel(writer_lk, index=None, sheet_name='学年成绩') for lk in lk_class: class_sort = sort_class_lk(score_lk, lk) writer_lk.save() writer_lk.close() # #============整理出文科成绩及分班成绩计算总分、总分排名、班级排名================== wk_yw = yw_score.loc[(yw_score.班级.isin(wk_class)), ['班级','姓名','语文']] wk_sx = sxwk_score[['姓名','数学']] wk_yy = yy_score.loc[(yy_score.班级.isin(wk_class)), ['姓名','英语']] wk_k3 = wkzh_score[['姓名','政治','历史','地理','文综']] wk_list = [wk_yw, wk_sx, wk_yy, wk_k3] score_wk = (reduce(lambda left, right: pd.merge(left, right, on='姓名'), wk_list)) score_wk['总分'] = (score_wk['语文'] + score_wk['数学'] + score_wk['英语'] + score_wk['文综']).round(0) def sort_class_wk(score_garde,name): class_sort = score_garde.loc[score_garde.班级 == name, :] class_sort = class_sort.sort_values(by=['总分'], ascending=False) class_sort['班级排名'] = class_sort['总分'].rank(ascending=0,method='min') class_sort.to_excel(writer_wk, index=None, sheet_name=name) wk_grade_sort = sort_grade(score_wk) wk_grade_sort.to_excel(writer_wk, index=None, sheet_name='学年成绩') for wk in wk_class: class_sort = sort_class_wk(wk_grade_sort, wk) writer_wk.save() writer_wk.close() 2、成绩区间分割与统计 #coding:utf-8 import numpy as np import pandas as pd from functools import reduce fpath_lk="./整理后的成绩/2020一模理科总成绩及各班级成绩.xlsx" fpath_wk="./整理后的成绩/2020一模文科总成绩及各班级成绩.xlsx" writer_lk = pd.ExcelWriter('./整理后的成绩/2020一模理科成绩区间分布统计.xlsx') writer_wk = pd.ExcelWriter('./整理后的成绩/2020一模文科成绩区间分布统计.xlsx') lk = pd.read_excel(fpath_lk, None) #获取表格中的所有工作表的内容 wk = pd.read_excel(fpath_wk, None) #===================1.定义区间分割函数===================================== def cut_750(score_750,len): bins_750= [0,370,380,390,400,410,420,430,440,450,460,470,480,490,500,510,520,530,540,550,560,570,580,590,600,620,640,660,750] labels_750 = ['0-370','370-379','380-389','390-399','400-409','410-419','420-429','430-439','440-449','450-459','460-469','470-479','480-489','490-499','500-509','510-519','520-529','530-539','540-549','550-559','560-569','570-579','580-589','590-599','600-619','620-639','640-659','660-750'] cut_750 = pd.cut(score_750, bins_750, labels=labels_750, right=False) qj = pd.DataFrame({'区间':pd.value_counts(cut_750).index,'人数':pd.value_counts(cut_750),'百分比':((pd.value_counts(cut_750))/len).round(3).apply(lambda x: format(x, '.2%'))}).sort_values(by='区间', ascending=False) qj = qj.reset_index(drop=True) return qj def cut_150(score_150,len): bins_150 = [0,30,60,90,120,150] labels_150 = ['0-30', '30-60', '60-90', '90-120', '120-150'] cut_150 = pd.cut(score_150, bins_150, labels=labels_150, right=False) qj = pd.DataFrame({'区间':pd.value_counts(cut_150).index,'人数':pd.value_counts(cut_150),'百分比':((pd.value_counts(cut_150))/len).round(3).apply(lambda x: format(x, '.2%'))}).sort_values(by='区间') 其他源代码及始数据已上传,欢迎各位借鉴,第一次编程,希望网友们能指点不足之处,联系qq:912182988
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值