案列要求
1、训练要点
(1)掌握使用seaborn库或者matplotlib库进行数据可视化的方法
(2)掌握撰写可视化分析报告的方法
2、需求说明
在现实生活中,学生的成绩与表现往往受制于多方面的因素。在教学研究中,除去对各科目考试结果本身的分析外,如果能够深入地对学生其他信息(如对学生家庭背景、性别、饮食、课前准备等影响因素)进行分析,那么老师将会进一步了解学生在考试中的表现。学生考试成绩数据集中包含8各字段,共计1000条数据,其字段信息说明如下表所示。
表:学生考试成绩数据集中的字段信息说明
为了了解不同性别的学生在数学、阅读、写作中的表现,了解父母受教育程度对学生数学、阅读、写作是否有影响,了解午餐标准对学生成绩是否有影响,了解考试准备充分是否有助于提高学生成绩,需要对学生考试成绩数据集进行数据读取、处理、可视化分析。
(1)使用Pandas库读取文件,查看原始数据的相关特征和描述信息,检查是否有空值。
(2)分别获取数据框中的阅读成绩、数学成绩、写作成绩3个字段,累加求和计算出每个学生的总分total_score,再除以3得到平均分percentage。
(3)设置各门课程及格线为60分,分别判断学生是否通过(Fail/Pass)每门课,合并新的数据列pass_reading、pass_math、pass_writing。
(4)判断每个学生的整体状态是否通过。如果3门课中有一门为Fail,则最后考核为Fail,合并新的数据列status。
(5)对于总分是Pass的数据,根据平均分设置5级制成绩,即percentage大于等于90分为优秀,8089分为良好,7079分为中等,60~69分为几个,其他为不及格。
(6)绘制可视化图形。
绘制父母受教育程度的水平柱状图
绘制全体学生成绩分布饼图
绘制各科成绩分布直方图
绘制父母受教育程度与前置课程是否完成统计分类图
绘制成绩评级与性别分布箱线图
绘制午餐标准与总成绩的性别分类散点图
绘制各特征的相关热力图
背景
为了了解不同性别的学生在数学、阅读、写作中的表现,了解父母受教育程度对学生数学、阅读、写作是否有影响,了解午餐标准对学生成绩是否有影响,了解考试准备充分是否有助于提高学生成绩,需要对学生考试成绩数据集进行数据读取、处理、可视化分析。在当今社会,教育是许多人生中最重要的一部分。随着数据分析和可视化技术的不断发展,越来越多的人开始将这些技术应用于教育领域,以帮助学校、家长和政府更好地管理和决策。而Python作为一种流行的编程语言,其数据分析和可视化能力已经得到广泛认可和使用。本文介绍了一个基于Python脚本的学生特征和成绩分析方案,旨在探究不同特征对学生成绩的影响,并提供有力支持和参考,为学校和家长提供更有效的教育决策。
一、处理数据
import pandas as pdimport pandas as pd# 使用 GBK 编码方式读取文件df = pd.read_csv("StudentsPerformance.csv", encoding="gbk")# 查看数据的前几行print(df.head())# 查看数据的基本信息,包括每列数据的类型和非空数量等print(df.info())# 查看数据的统计信息,包括每列数据的基本统计量(如均值、标准差、最大值、最小值等)print(df.describe())# 检查是否有空值print(df.isnull().sum())
这段代码主要使用了 Python 的 Pandas 库对名为 “StudentsPerformance.csv” 的 CSV 文件进行了分析。在运行这段代码后,它会执行以下几个操作:
使用 Pandas 库的 read_csv() 函数读取 “StudentsPerformance.csv” 文件中的数据,并将其存储在一个名为 df 的 Dataframe 对象中。
执行 df.head() 函数,可以显示出这个 Dataframe 对象的前五行,方便我们初步查看数据。
执行 df.info() 函数,可以打印出 Dataframe 的基本信息,包括列数、每列名称、每列中非空值的数量和数据类型等
执行 df.describe() 函数,可以打印出 Dataframe 中各列数据的统计信息,如均值、标准差、最大值、最小值等。
执行 df.isnull().sum() 函数,可以检查 Dataframe 中是否有缺失值,统计每列缺失值的数量,并将其打印出来。
结果: 性别 民族 父母教育程度 午餐 课程完成情况 数学成绩 阅读成绩 写作成绩0 女 B 学士学位 标准 未完成 72 72 741 女 C 大学未毕业 标准 完成 69 90 882 女 B 硕士学位 标准 未完成 90 95 933 男 A 副学士学位 自由/减少 未完成 47 57 444 男 C 大学未毕业 标准 未完成 76 78 75RangeIndex: 1000 entries, 0 to 999Data columns (total 8 columns): # Column Non-Null Count Dtype --- ------ -------------- ----- 0 性别 1000 non-null object 1 民族 1000 non-null object 2 父母教育程度 1000 non-null object 3 午餐 1000 non-null object 4 课程完成情况 1000 non-null object 5 数学成绩 1000 non-null int64 6 阅读成绩 1000 non-null int64 7 写作成绩 1000 non-null int64 dtypes: int64(3), object(5)memory usage: 62.6+ KBNone 数学成绩 阅读成绩 写作成绩count 1000.00000 1000.000000 1000.000000mean 66.08900 69.169000 68.054000std 15.16308 14.600192 15.195657min 0.00000 17.000000 10.00000025% 57.00000 59.000000 57.75000050% 66.00000 70.000000 69.00000075% 77.00000 79.000000 79.000000max 100.00000 100.000000 100.000000性别 0民族 0父母教育程度 0午餐 0课程完成情况 0数学成绩 0阅读成绩 0写作成绩 0dtype: int64
二、选取阅读成绩、数学成绩、写作成绩3个字段,计算总分和平均分
# 选取阅读成绩、数学成绩、写作成绩3个字段,计算总分和平均分df['总分'] = df.iloc[:,5:8].sum(axis=1)df['平均分'] = df['总分'] / 3# 查看计算结果print(df[['阅读成绩', '数学成绩', '写作成绩', '总分', '平均分']].head())
这段代码的作用是从 DataFrame 对象 df 中选取阅读成绩、数学成绩、写作成绩3个字段,并计算每位学生的总分和平均分。具体解释如下:
df.iloc[:, 5:8] 表示选取第6、7、8列(阅读成绩、数学成绩、写作成绩),使用 sum(axis=1) 对每行求和,将每位学生的总分添加到 df 中。计算每位学生的平均分,即将每位学生的总分除以3,并将其添加到 df 中。使用 df[['阅读成绩', '数学成绩', '写作成绩', '总分', '平均分']] 选取 DataFrame 对象 df 中的 阅读成绩、数学成绩、写作成绩、总分、平均分这5个字段,并使用 head() 方法打印出前五行数据。
总之,这段代码的目的是对 DataFrame 对象 df 的特定字段进行处理,并将处理结果添加到 df 中。它计算了每位学生的总分和平均分,并把这两个指标加入到了原始数据中,方便进一步统计和分析。最后,使用 print 函数输出了所选的字段以及新增字段的结果,以便于我们查看计算结果。
三、设置及格线为60分,并使用 lambda 函数判断每位学生是否通过各门课程
阅读成绩 数学成绩 写作成绩 总分 平均分0 72 72 74 218 72.6666671 90 69 88 247 82.3333332 95 90 93 278 92.6666673 57 47 44 148 49.3333334 78 76 75 229 76.333333
# 设置及格线为60分,并使用 lambda 函数判断每位学生是否通过各门课程df['pass_reading'] = df['阅读成绩'].apply(lambda x: 'Pass' if x >= 60 else 'Fail')df['pass_math'] = df['数学成绩'].apply(lambda x: 'Pass' if x >= 60 else 'Fail')df['pass_writing'] = df['写作成绩'].apply(lambda x: 'Pass' if x >= 60 else 'Fail')# 打印修改后的数据帧print(df.head())
这段代码的主要作用是,首先设置及格线为 60 分,然后使用 lambda 函数判断每位学生是否通过阅读、数学和写作三门课程,并将结果存储到 df 新添加的三列 pass_reading、pass_math 和 pass_writing 中。具体解释如下:
使用 apply 方法和 lambda 函数,对阅读成绩、数学成绩、写作成绩这三列,使用 if 判断语句,若成绩大于等于 60,则将该学生的值设定为 ‘Pass’,否则设定为 ‘Fail’,并将判断结果添加到 DataFrame 对象 df 的新列中。
因为 DataFrame 对象 df 的三列 pass_reading、pass_math 和 pass_writing 新添加了判断结果,所以打印出修改后的 DataFrame 对象 df,以便于我们查看结果。
总之,这段代码的目的是对 DataFrame 对象 df 的阅读成绩、数学成绩、写作成绩这三列数据进行判断,并将判断结果添加到 df 新添加的三列中。它使用了 apply 方法和 lambda 函数来对每个成绩进行判断,并根据判断结果添加到相应的新列中。这样做有利于我们更好地判断每位学生是否通过各门课程,并能够在进一步分析中帮助我们更精准地对学生成绩进行评估。
性别 民族 父母教育程度 午餐 课程完成情况 数学成绩 阅读成绩 写作成绩 总分 平均分 pass_reading 0 女 B 学士学位 标准 未完成 72 72 74 218 72.666667 Pass 1 女 C 大学未毕业 标准 完成 69 90 88 247 82.333333 Pass 2 女 B 硕士学位 标准 未完成 90 95 93 278 92.666667 Pass 3 男 A 副学士学位 自由/减少 未完成 47 57 44 148 49.333333 Fail 4 男 C 大学未毕业 标准 未完成 76 78 75 229 76.333333 Pass pass_math pass_writing 0 Pass Pass 1 Pass Pass 2 Pass Pass 3 Fail Fail 4 Pass Pass
四、使用 apply() 函数和 lambda 表达式判断每个学生的整体状态是否通过,并将判断结果存储在新的数据列中
# 使用 apply() 函数和 lambda 表达式判断每个学生的整体状态是否通过,并将判断结果存储在新的数据列中df['情况'] = df.apply(lambda x: 'Pass' if x['pass_reading'] == 'Pass' and x['pass_math'] == 'Pass' and x['pass_writing'] == 'Pass' else 'Fail', axis=1)# 打印修改后的数据帧print(df.head())
性别 民族 父母教育程度 午餐 课程完成情况 数学成绩 阅读成绩 写作成绩 总分 平均分 pass_reading 0 女 B 学士学位 标准 未完成 72 72 74 218 72.666667 Pass 1 女 C 大学未毕业 标准 完成 69 90 88 247 82.333333 Pass 2 女 B 硕士学位 标准 未完成 90 95 93 278 92.666667 Pass 3 男 A 副学士学位 自由/减少 未完成 47 57 44 148 49.333333 Fail 4 男 C 大学未毕业 标准 未完成 76 78 75 229 76.333333 Pass
这段代码的目的是使用 apply() 函数和 lambda 表达式计算出每个学生的整体状态是否通过,并将结果存储在 DataFrame 对象 df 的新列 ‘情况’ 中。具体解释如下:
使用 apply() 函数和 lambda 表达式,对 DataFrame 对象 df 进行遍历并应用 lambda 函数,axis=1 表示沿着行方向进行操作。对于每个学生,判断其阅读、数学、写作三科成绩是否全部通过,如果全部通过则该学生整体通过,否则整体不通过。
根据判断结果,将"Pass"或"Fail"存储到 DataFrame 对象 df 的新列’情况’中。
打印输出修改后的 DataFrame 对象 df,以便于我们查看计算结果。
总之,这段代码的目的是对 DataFrame 对象 df 的三门科目成绩是否通过进行整体判断,并将判断结果存储到一个新列中,这样可以更加方便地进行学生成绩评估。
pass_math pass_writing 情况 0 Pass Pass Pass 1 Pass Pass Pass 2 Pass Pass Pass 3 Fail Fail Fail 4 Pass Pass Pass
五、计算每个学生的总分和平均分,并使用条件表达式判断成绩等级,并将判断结果存储在新的数据列中
# 计算每个学生的总分和平均分,并使用条件表达式判断成绩等级,并将判断结果存储在新的数据列中df['总分'] = df['数学成绩'] + df['阅读成绩'] + df['写作成绩']df['平均分'] = df['总分'] / 3df['等级'] = df.apply(lambda x: '优秀' if x['平均分'] >= 90 else '良好' if x['平均分'] >= 80 else '中等' if x['平均分'] >= 70 else '及格' if x['平均分'] >= 60 else '不及格', axis=1)# 打印修改后的数据帧print(df.head())
这段代码的目的是计算每个学生的总分和平均分,并根据条件表达式判断成绩等级,并将判断结果存储在 DataFrame 对象 df 的新列’等级’中。具体解释如下:
首先,计算每个学生的总分和平均分,将其存储在 DataFrame 对象 df 的’总分’和’平均分’列中。
使用 apply() 函数和 lambda 表达式遍历 DataFrame 对象 df,axis=1 表示沿着行方向进行操作。对于每个学生,根据其平均分使用条件表达式判断其成绩等级,例如如果平均分大于等于 90 分,则为优秀,大于等于 80 分则为良好,以此类推,将其判断结果存储到 DataFrame 对象 df 的新列’等级’中。
打印输出修改后的 DataFrame 对象 df,以便于我们查看计算结果。
总之,这段代码的目的是对 DataFrame 对象 df 的三门科目成绩进行计算并判断成绩等级,将判断结果存储到一个新的数据列中。这样可以更加方便地对学生成绩做出评估和分析。
性别 民族 父母教育程度 午餐 课程完成情况 数学成绩 阅读成绩 写作成绩 总分 平均分 pass_reading 0 女 B 学士学位 标准 未完成 72 72 74 218 72.666667 Pass 1 女 C 大学未毕业 标准 完成 69 90 88 247 82.333333 Pass 2 女 B 硕士学位 标准 未完成 90 95 93 278 92.666667 Pass 3 男 A 副学士学位 自由/减少 未完成 47 57 44 148 49.333333 Fail 4 男 C 大学未毕业 标准 未完成 76 78 75 229 76.333333 Pass pass_math pass_writing 情况 等级 0 Pass Pass Pass 中等 1 Pass Pass Pass 良好 2 Pass Pass Pass 优秀 3 Fail Fail Fail 不及格 4 Pass Pass Pass 中等
六、数据可视化
1.统计每个家长受教育水平的人数,并绘制水平柱状图
import seaborn as snsimport matplotlib.pyplot as plt# 指定字体plt.rcParams['font.sans-serif'] = ['SimHei']# 统计每个家长受教育水平的人数,并绘制水平柱状图edu_counts = df['父母教育程度'].value_counts()plt.bar(edu_counts.index, edu_counts.values)plt.xlabel('父母教育程度')plt.ylabel('人数')plt.title('父母受教育程度的水平柱状图')plt.show()
2. 统计及格和不及格的人数,并绘制饼图
# 统计及格和不及格的人数,并绘制饼图pass_counts = df['情况'].value_counts()labels = ['及格', '不及格']sizes = [pass_counts['Pass'], pass_counts['Fail']]
plt.pie(sizes, labels=labels, autopct='%1.1f%%')plt.title('全体学生成绩分布饼图')plt.axis('equal')plt.show()
3. 绘制数学成绩、阅读成绩和写作成绩的直方图
# 绘制数学成绩、阅读成绩和写作成绩的直方图plt.hist(df['数学成绩'], bins=10, alpha=0.5, label='math score')plt.hist(df['阅读成绩'], bins=10, alpha=0.5, label='reading score')plt.hist(df['写作成绩'], bins=10, alpha=0.5, label='writing score')plt.legend(loc='upper right')plt.xlabel('成绩')plt.ylabel('人数')plt.title('各科成绩分布直方图')plt.show()
4. 绘制父母受教育程度和前置课程是否完成的分类图
# 绘制父母受教育程度和前置课程是否完成的分类图sns.countplot(x='父母教育程度', data=df, hue='课程完成情况')plt.title('父母受教育程度与前置课程是否完成统计分类图')plt.show()
5. 绘制成绩评级和性别分布的箱线图
# 绘制成绩评级和性别分布的箱线图sns.boxplot(x='等级', y='总分', hue='性别', data=df)plt.title('成绩评级与性别分布箱线图')plt.show()
6. 绘制午餐标准和总成绩的性别分类散点图
# 绘制午餐标准和总成绩的性别分类散点图sns.scatterplot(x='午餐', y='总分', hue='性别', data=df)plt.title('午餐标准与总成绩的性别分类散点图')plt.show()
7. 计算各特征之间的相关系数,并绘制热力图
corr = df.corr()sns.heatmap(corr, annot=True, cmap='coolwarm')plt.title('各特征的相关热力图')plt.show()
七、总结
通过对学生数据的分析和可视化,本Python脚本探讨了学生的不同特征与其成绩之间的关系,并得出了多个结论。其中包括父母受教育程度普遍较高、女性学生总成绩明显高于男性学生等。这些结论为学校、家长和政府制定更有效的教育方案提供了非常有价值的参考。
此外,使用Matplotlib和Seaborn这两个强大的可视化库,使得数据结果更加直观和易懂。通过直观的图表呈现,我们可以更清晰地看到数据分布和相互关系,从而更准确地分析和解读数据。
需要注意的是,尽管本脚本得出了多个结论,但这些结论并不一定适用于所有情况,仍需考虑实际情况和背景。同时,还可以通过进一步探究和分析数据,寻求更深层次的规律和结论,为教育领域提供更多的参考和指导。
总之,本Python脚本为教育领域的数据分析和研究提供了一个好的起点,也为学生特征和成绩之间的关系提供了有力支持。在今后的学生管理和教育实践中,我们应该进一步挖掘数据的潜力,为学生成长和发展提供更有效的帮助和支持。
八、完整代码
以下代码为基于 Pandas 库对学生表现数据进行的一系列操作和可视化,主要包括数据读取、数据清洗、数据计算、数据分析和数据可视化等方面的内容。其中,我们可以看到对于数据的大量处理操作,例如:查看数据的前几行和基本信息、计算总分和平均分、判断每门课程是否及格、判断整体状态是否通过、计算成绩等级、统计分类图、箱线图、散点图、热力图等。这些操作可以帮助我们更好地了解和分析该数据集,以便后续做出更好的决策和指导。
import pandas as pdimport pandas as pd# 使用 GBK 编码方式读取文件df = pd.read_csv("StudentsPerformance.csv", encoding="gbk")# 查看数据的前几行print(df.head())# 查看数据的基本信息,包括每列数据的类型和非空数量等print(df.info())# 查看数据的统计信息,包括每列数据的基本统计量(如均值、标准差、最大值、最小值等)print(df.describe())# 检查是否有空值print(df.isnull().sum())# 选取阅读成绩、数学成绩、写作成绩3个字段,计算总分和平均分df['总分'] = df.iloc[:,5:8].sum(axis=1)df['平均分'] = df['总分'] / 3# 查看计算结果print(df[['阅读成绩', '数学成绩', '写作成绩', '总分', '平均分']].head())# 设置及格线为60分,并使用 lambda 函数判断每位学生是否通过各门课程df['pass_reading'] = df['阅读成绩'].apply(lambda x: 'Pass' if x >= 60 else 'Fail')df['pass_math'] = df['数学成绩'].apply(lambda x: 'Pass' if x >= 60 else 'Fail')df['pass_writing'] = df['写作成绩'].apply(lambda x: 'Pass' if x >= 60 else 'Fail')# 打印修改后的数据帧print(df.head())# 使用 apply() 函数和 lambda 表达式判断每个学生的整体状态是否通过,并将判断结果存储在新的数据列中df['情况'] = df.apply(lambda x: 'Pass' if x['pass_reading'] == 'Pass' and x['pass_math'] == 'Pass' and x['pass_writing'] == 'Pass' else 'Fail', axis=1)# 打印修改后的数据帧print(df.head())# 计算每个学生的总分和平均分,并使用条件表达式判断成绩等级,并将判断结果存储在新的数据列中df['总分'] = df['数学成绩'] + df['阅读成绩'] + df['写作成绩']df['平均分'] = df['总分'] / 3df['等级'] = df.apply(lambda x: '优秀' if x['平均分'] >= 90 else '良好' if x['平均分'] >= 80 else '中等' if x['平均分'] >= 70 else '及格' if x['平均分'] >= 60 else '不及格', axis=1)# 打印修改后的数据帧print(df.head())import seaborn as snsimport matplotlib.pyplot as plt# 指定字体plt.rcParams['font.sans-serif'] = ['SimHei']# 统计每个家长受教育水平的人数,并绘制水平柱状图edu_counts = df['父母教育程度'].value_counts()plt.bar(edu_counts.index, edu_counts.values)plt.xlabel('父母教育程度')plt.ylabel('人数')plt.title('父母受教育程度的水平柱状图')plt.show()# 统计及格和不及格的人数,并绘制饼图pass_counts = df['情况'].value_counts()labels = ['及格', '不及格']sizes = [pass_counts['Pass'], pass_counts['Fail']]plt.pie(sizes, labels=labels, autopct='%1.1f%%')plt.title('全体学生成绩分布饼图')plt.axis('equal')plt.show()# 绘制数学成绩、阅读成绩和写作成绩的直方图plt.hist(df['数学成绩'], bins=10, alpha=0.5, label='math score')plt.hist(df['阅读成绩'], bins=10, alpha=0.5, label='reading score')plt.hist(df['写作成绩'], bins=10, alpha=0.5, label='writing score')plt.legend(loc='upper right')plt.xlabel('成绩')plt.ylabel('人数')plt.title('各科成绩分布直方图')plt.show()# 绘制父母受教育程度和前置课程是否完成的分类图sns.countplot(x='父母教育程度', data=df, hue='课程完成情况')plt.title('父母受教育程度与前置课程是否完成统计分类图')plt.show()# 绘制成绩评级和性别分布的箱线图sns.boxplot(x='等级', y='总分', hue='性别', data=df)plt.title('成绩评级与性别分布箱线图')plt.show()# 绘制午餐标准和总成绩的性别分类散点图sns.scatterplot(x='午餐', y='总分', hue='性别', data=df)plt.title('午餐标准与总成绩的性别分类散点图')plt.show()# 计算各特征之间的相关系数,并绘制热力图corr = df.corr()sns.heatmap(corr, annot=True, cmap='coolwarm')plt.title('各特征的相关热力图')plt.show()
附录: 数据文件
本次案列所用到的CSV数据