python pandas "数智教育"数据可视化分析

数据介绍:

数据来源于由宁波教育局与阿里云计算有限公司主办,宁波效实中学承办的"数智教育"数据可视化创新大赛数据集。

https://www.heywhale.com/mw/dataset/5eb3f5f9366f4d002d76e70f

1_teacher.csv:包含了近五年各班各学科的教师信息
term:学期
cla_id:班级ID
cla_Name:班级名
gra_Name:年级名
sub_id:学科ID
sub_Name:学科名
bas_id:教师id
bas_Name:教师名

2_studentinfo.csv:包含了当前在校学生详细信息
bf_StudentID,学生ID
bf_Name,学生姓名
bf_sex,性别
bf_nation,民族
bf_BornDate,出生日期(年)
cla_Name,班级名(与teacher.csv的cla_name对应)
bf_NativePlace,家庭住址(省市或省)
Bf_ResidenceType,家庭类型
bf_policy,政治面貌
cla_id,班级ID
cla_term,班级学期
bf_zhusu,是否住校
bf_leaveSchool,是否退学
bf_qinshihao,宿舍号

3_kaoqin.csv
kaoqin_id,考勤ID
qj_term,学期
DataDateTime,时间和日期
ControllerID,对应考勤类型表里的ControllerID
controler_name,考勤名称
control_task_order_id,对应考勤类型表里的control_task_order_id
bf_studentID,学生ID,对应学生信息表
bf_Name,学生姓名
cla_Name,班级名
bf_classid班级ID

4_kaoqintype.csv:考勤类型
controler_id,考勤类型id
controler_name,考勤类型名称
control_task_order_id,考勤事件id
control_task_name:考勤事件名

5_chengji.csv:学生成绩
mes_TestID,考试id
exam_number,考试编码
exam_numname,考试编码名称
mes_sub_id,考试学科id
mes_sub_name,考试学科名
exam_term,考试学期
exam_type,考试类型(对应考试类型表)
exam_sdate,考试开始时间
mes_StudentID,学生id
mes_Score,考试成绩(-1为作弊,-2为缺考,-3为免考)
mes_Z_Score,换算成Z-score(Z-score、T-score、等第 是一种学生成绩评价方式,可以参考网络百科)
mes_T_Score,换算成T-score
mes_dengdi:换算成等第(参见:https://tianchi.aliyun.com/forum/postDetail?spm=5176.12281978.0.0.65ca76d8kaGnld&postId=47777)

6_exam_type.csv:考试类型
EXAM_KIND_ID:考试类型id
EXAM_KIND_NAME:考试类型名称

7_consumption.csv:本学年学生消费信息
DealTime,消费时间
MonDeal,消费金额
bf_studentID:对应学生信息表studentid
AccName,姓名
PerSex,性别

特别说明:
1.由于人为登记等不可避免原因,某些字段可能存在缺失或者异常值
2.从班级名可以看出,从2017年开始学校陆续启用了新校区,2018年新校区统一命名为型为“白-高二(01)”和“东-高二(01)”的班级名
3.考勤类型中的“校服[移动考勤]”指的是没穿校服3.考勤类型中的“校服[移动考勤]”指的是没穿校服
#导入用到的库
import pandas as pd
import matplotlib.pyplot as plt

1.各科成绩分布图


结果分析:

1.体育,美术,音乐,通用技术成绩很稳定均匀,与之有关的影响因素较少,在于学生的个人选择及天赋,可不必投入较多资源;

2.该学校的数学,英语,语文平均成绩明显较其他科目成绩好,说明该校的主要的教师资源,人力资源主要集中在三大学科上;

代码:

#读取成绩文件
chengji_data=pd.read_csv("5_chengji.csv")
#mes_Score,考试成绩(-1为作弊,-2为缺考,-3为免考) 删除以上数据
chengji_data1=chengji_data[chengji_data["mes_Score"]>0]
#查看每列空值
chengji_data1.isna().sum()
#按课程名分组
chengji_group=chengji_data1.groupby("mes_sub_name")
#按学年分组
chengji_group_year=chengji_data1.groupby("exam_term")
#建立空表
data=pd.DataFrame({"data":[]})
boxes=[]
boxes_name=[]
#遍历按课程名分组的所有课程名及成绩
for k,g in chengji_group:
    if k!='data':
        boxes.append(g['mes_Score'])
        boxes_name.append(k)
#全部学年集合
chengji_year=[]       
for k1,g1 in chengji_group_year:
    chengji_year.append(k1)
    

#定义图颜色
color = dict(boxes='DarkGreen', whiskers='DarkOrange', medians='DarkBlue', caps='Gray')
plt.rcParams['font.sans-serif']=['SimHei']##中文乱码问题!
plt.rcParams['axes.unicode_minus']=False#横坐标负号显示问题!
plt.figure(figsize=(10,5))        #图片大小为10*5
plt.boxplot(boxes,whis=2,showmeans=True,showbox = True,labels=boxes_name,showfliers=False)
plt.grid(axis="y",alpha=0.4)#绘制
plt.show()

2.历年成绩对比曲线


结果分析:

1.从图上可以看出所有成绩从2013-2015都比较平稳,许多课程从2015年开始成绩开始呈下降趋势;

2.可能跟近年来一直要求的素质教育有关,出题的方式及难度都有问题,以及老师的过往经验的不适用性;

代码:

#新建模板以分组日期集合为index
data1=pd.DataFrame({"date":chengji_year})
data1.set_index("date", inplace=True)#设置日期为index
for k,g in chengji_group:#遍历课程分组
    print(k)
    chengji_group_year=g.groupby("exam_term")#按学年分组取年和平均成绩写入新表
    for k_y,g_y in chengji_group_year:
        print(k_y,g_y)
        data1.loc[k_y,k]=g_y["mes_Score"].mean()


plt.figure(figsize=(12,5))        #图片大小为12*5
plt.plot(data1,ms=5,marker='.',label=data1.columns)
plt.grid(alpha=0.4)#绘制
plt.legend(loc="lower right")#显示图例
plt.show()

3.考试类型与成绩对比分析


结果分析:

1.考试类型与各科成绩波动较大,可能存在明显的难易程度不同;

2.学校的期中期末考试成绩一般分布可以,其他类型考试波动很大;

代码:

#读取考试类型表
kaoshi_lx=pd.read_csv("6_exam_type.csv")
kaoshi_lx.set_index("EXAM_KIND_ID", inplace=True)#设置类型为index



#按课程分组遍历
for k,g in chengji_group:
    #print(k)
    #按考试类型分组
    chengji_group_year=g.groupby("exam_type")
    #取考试类型和平均成绩
    for k_y,g_y in chengji_group_year:
        #print(k_y,g_y)
        kaoshi_lx.loc[k_y,k]=g_y["mes_Score"].mean()
kaoshi_lx   

4.政治面貌/民族占比

#读取学生信息表
zhengzhi=pd.read_csv("2_student_info.csv")
#按政治面貌分组
zhengzhi_group=zhengzhi.groupby("bf_policy").count()
#按民族分组
minzu_group=zhengzhi.groupby("bf_nation").count()

zhengzhi_group["bf_StudentID"].plot.pie()
minzu_group["bf_StudentID"].plot.pie()




5.学生消费信息分布



结果分析:

1.图中可以看出各学生总消费以及每次消费金额都成明显的正态分布,说明该学校整体消费趋势正常

2.该数据统计了6个月(2018.7-2019.1)六个月的消费情况,平均来说该学校学生每月平均消费在[250,500];

3.每次消费金额在7-10之间,但存在可能购买文具等小物件上,这里不做详细的分类讨论;

代码

#读取消费信息表
sale=pd.read_csv("7_consumption.csv")
sale["DealTime"]=pd.to_datetime(sale["DealTime"])#转换日期格式
ym_mean = sale.groupby([sale.DealTime.dt.year, sale.DealTime.dt.month]).sum() #按月求和
ym_mean["MonDeal"]=abs(ym_mean["MonDeal"])
ym_mean["MonDeal"].plot.bar()
#学生消费top
sale_top= sale.groupby("bf_StudentID").sum() #按学生求和
sale_top.sort_values(by=["MonDeal"],inplace=True)
sale_top["MonDeal"]=abs(sale_top["MonDeal"])
sale_top["MonDeal"].head(20).plot.bar()

6.学生考勤分析


代码

#读取考勤表
kaoqin_df=pd.read_csv("3_kaoqin.csv")
#使用正则表达式清洗班级名
for i in range(len(kaoqin_df)):
    str1=re.sub(u"(.*?)|白-|[A-Z]|东-|[0-9]", "",kaoqin_df.loc[i,"cla_Name"])
    str1=str1.replace(" ","")
    kaoqin_df.loc[i,"cla_Name1"]=str1
#取所有考勤汇总
kaoqin_type=kaoqin_df.groupby(["controler_name"]).count()
kaoqin_type.index
kaoqin_moban=pd.DataFrame({"type":kaoqin_type.index})
kaoqin_moban.set_index("type", inplace=True)#设置类型为index
kaoqin_moban
#按新的班级名分组
kaoqin_gruop=kaoqin_df.groupby(["cla_Name1"])
#遍历分组
for k,g in kaoqin_gruop:
    print(k)
    #按考勤类型汇总
    tmp=g.groupby(["controler_name"]).count()
    for j1 in tmp.index:
        #print(tmp.loc[j1,"kaoqing_id"])
        #根据考勤类型写入新表
        kaoqin_moban.loc[j1,k]=tmp.loc[j1,"kaoqing_id"]
kaoqin_moban


labels = list(kaoqin_moban.columns)
first = list(kaoqin_moban["高一"])
second = list(kaoqin_moban["高二"])
third = list(kaoqin_moban["高三"])
data = [first, second, third]
x = range(0,8)
width = 0.35
# 将bottom_y元素都初始化为0
bottom_y = [0] * 8
# 计算每组柱子的总和,为计算百分比做准备
sums = [sum(i) for i in zip(first, second, third)]
#print(first,labels,sums)
plt.figure(figsize=(12,5))  
for i in data:
    # 计算每个柱子的高度,即百分比
    y = [a/b for a, b in zip(i, sums)]
    #print(x,y)
    plt.bar(x, y, width, bottom=bottom_y)
    # 计算bottom参数的位置
    bottom_y = [(a+b) for a, b in zip(y, bottom_y)]
plt.legend(labels,loc="right")
plt.xticks(x, kaoqin_moban.index)
plt.title('考勤分析')
plt.show()
   


labels = list(kaoqin_moban1.index)
da1 = list(kaoqin_moban1["操场考勤机"])
da2 = list(kaoqin_moban1["早退[移动考勤机]"])
da3 = list(kaoqin_moban1["校徽_早退"])
da4 = list(kaoqin_moban1["校服[移动考勤机]"])
da5 = list(kaoqin_moban1["离校[移动考勤机]"])
da6 = list(kaoqin_moban1["进校[移动考勤机]"])
da7 = list(kaoqin_moban1["迟到[移动考勤机]"])
da8 = list(kaoqin_moban1["迟到_晚到"])

data = [da1,da2,da3,da4,da5,da6,da7,da8]
x = range(0,3)
width = 0.35
# 将bottom_y元素都初始化为0
bottom_y = [0] * 3
# 计算每组柱子的总和,为计算百分比做准备
sums = [sum(i) for i in zip(da1,da2,da3,da4,da5,da6,da7,da8)]
#print(first,labels,sums)
plt.figure(figsize=(8,6))  
for i in data:
    # 计算每个柱子的高度,即百分比
    y = [a/b for a, b in zip(i, sums)]
    #print(x,y)
    plt.bar(x, y, width, bottom=bottom_y)
    # 计算bottom参数的位置
    bottom_y = [(a+b) for a, b in zip(y, bottom_y)]
plt.legend( kaoqin_moban1.columns,loc="upper center")
plt.xticks(x, kaoqin_moban1.index)
plt.title('考勤分析')
plt.show()
   


展开阅读全文

页面更新:2024-03-20

标签:遍历   柱子   考勤   班级   成绩   类型   课程   数据   考试   学生   信息

1 2 3 4 5

上滑加载更多 ↓
推荐阅读:
友情链接:
更多:

本站资料均由网友自行发布提供,仅用于学习交流。如有版权问题,请与我联系,QQ:4156828  

© CopyRight 2008-2024 All Rights Reserved. Powered By bs178.com 闽ICP备11008920号-3
闽公网安备35020302034844号

Top