Python从入门到实战 (10):实战入门:用 Python 做数据统计与可视化
经过前面九篇的学习,我们已经掌握了Python的核心基础——语法、数据结构、函数、面向对象、异常处理,现在终于到了“实战环节”!这篇我们会用一个完整的小项目——“学生成绩数据分析与可视化”,把所有知识点串联起来:用pandas快速处理数据,用matplotlib生成直观的图表(柱状图、折线图、饼图),最后封装成可复用的函数,还会加入异常处理确保程序稳定。全程跟着做,你就能亲手完成第一个Python实战项目!
一、实战准备:安装必要的第三方库
实战需要两个常用第三方库(不是Python自带的,需手动安装):
- pandas:数据处理“神器”,能快速读取Excel/CSV文件、做统计分析(求平均分、最高分等);
- matplotlib:Python最常用的绘图库,能生成柱状图、折线图等各种可视化图表。
1. 安装方法(Windows/macOS/Linux通用)
打开终端/命令提示符,输入以下指令(确保已激活之前创建的Python虚拟环境,避免环境冲突):
# 安装pandas和matplotlib
pip install pandas matplotlib openpyxl
openpyxl是辅助库,用于读取Excel文件(.xlsx格式),必须一起安装;- 安装成功后,在Python中输入
import pandas和import matplotlib.pyplot as plt,不报错就是安装完成。
二、实战案例:学生成绩数据分析与可视化
我们的实战流程分为四步:
- 准备数据:用Excel创建学生成绩表;
- 读取数据:用
pandas读取Excel文件,处理异常(如文件不存在); - 统计分析:计算平均分、最高分、及格率等核心指标;
- 可视化:用
matplotlib生成3类图表,直观展示分析结果。
步骤1:准备数据(Excel成绩表)
先创建一个Excel文件(命名为student_scores.xlsx),内容如下(也可直接手动输入,或用示例数据):
| 姓名 | 语文 | 数学 | 英语 | 物理 | 化学 |
|---|---|---|---|---|---|
| 小明 | 92 | 98 | 88 | 95 | 90 |
| 小红 | 85 | 82 | 93 | 80 | 88 |
| 小刚 | 78 | 65 | 72 | 68 | 70 |
| 小丽 | 95 | 90 | 96 | 89 | 92 |
| 小强 | 62 | 58 | 70 | 65 | 60 |
| 小芳 | 88 | 92 | 85 | 90 | 86 |
把这个文件保存到项目文件夹(和后续写的Python代码放在同一目录,避免路径错误)。
步骤2:读取数据(用pandas,加异常处理)
首先写代码读取Excel文件,并用try-except处理“文件不存在”“格式错误”等异常,确保程序不崩溃。
import pandas as pd
import matplotlib.pyplot as plt
import logging
# 解决matplotlib中文显示问题
plt.rcParams['font.sans-serif'] = ['WenQuanYi Zen Hei', 'SimHei', 'Arial Unicode MS']
plt.rcParams['axes.unicode_minus'] = False
# 1. 配置日志(记录关键步骤和错误)
logging.basicConfig(
level=logging.INFO,
format="%(asctime)s - %(levelname)s - %(message)s"
)
def read_score_data(file_path):
"""
读取Excel格式的学生成绩数据
参数:file_path - Excel文件路径
返回:成功返回pandas的DataFrame(数据表格),失败返回None
"""
try:
logging.info(f"开始读取成绩文件:{file_path}")
# 用pandas读取Excel,指定读取的sheet(默认第一个,这里用"成绩表")
# 若Excel只有一个sheet,可省略sheet_name参数
df = pd.read_excel(
file_path,
sheet_name="成绩表", # 对应Excel的sheet名称(需和你的Excel一致)
engine="openpyxl" # 读取.xlsx格式必须指定engine
)
# 简单验证数据格式:检查是否包含必要的列(姓名+各科)
required_columns = ["姓名", "语文", "数学", "英语", "物理", "化学"]
if not all(col in df.columns for col in required_columns):
logging.error("Excel文件格式错误:缺少必要的列(姓名/语文/数学/英语/物理/化学)")
print("❌ 错误:Excel文件缺少必要的列,请检查格式!")
return None
logging.info(f"成功读取数据,共{len(df)}名学生")
print("✅ 数据读取成功!前3条数据预览:")
print(df.head(3)) # 打印前3条数据,确认读取正确
return df
except FileNotFoundError:
logging.error(f"成绩文件不存在:{file_path}")
print(f"❌ 错误:文件{file_path}不存在,请检查路径!")
return None
except Exception as e:
logging.error(f"读取数据时发生未知错误:{str(e)}", exc_info=True)
print(f"❌ 未知错误:{str(e)},请查看日志获取详情!")
return None
# 调用函数读取数据(确保Excel文件和代码在同一目录)
if __name__ == "__main__":
score_df = read_score_data("student_scores.xlsx")
运行代码后,若Excel文件正确,会打印前3条数据预览,类似:
2024-06-02 14:30:00,000 - INFO - 开始读取成绩文件:student_scores.xlsx
2024-06-02 14:30:00,000 - INFO - 成功读取数据,共6名学生
✅ 数据读取成功!前3条数据预览:
姓名 语文 数学 英语 物理 化学
0 小明 92 98 88 95 90
1 小红 85 82 93 80 88
2 小刚 78 65 72 68 70
步骤3:统计分析(计算核心指标)
读取数据后,我们需要计算“各科平均分”“每个学生总分”“及格率”等核心指标,用函数封装逻辑,让代码更清晰。
def analyze_score_data(df):
"""
分析学生成绩数据,计算核心指标
参数:df - 读取后的DataFrame数据
返回:包含所有分析结果的字典
"""
logging.info("开始分析成绩数据")
# 1. 计算各科成绩指标(平均分、最高分、最低分、及格率)
subjects = ["语文", "数学", "英语", "物理", "化学"]
subject_analysis = {}
for subject in subjects:
# 平均分(保留1位小数)
avg_score = round(df[subject].mean(), 1)
# 最高分
max_score = df[subject].max()
# 最低分
min_score = df[subject].min()
# 及格率(≥60分为及格,保留2位小数)
pass_rate = round((df[subject] >= 60).sum() / len(df) * 100, 2)
subject_analysis[subject] = {
"平均分": avg_score,
"最高分": max_score,
"最低分": min_score,
"及格率(%)": pass_rate
}
# 2. 计算每个学生的总分和平均分(新增列到DataFrame)
df["总分"] = df[subjects].sum(axis=1) # axis=1表示按行求和
df["平均分"] = round(df[subjects].mean(axis=1), 1)
# 3. 按总分排序(从高到低)
df_sorted = df.sort_values("总分", ascending=False).reset_index(drop=True)
# 4. 统计总分排名前3的学生
top3_students = df_sorted[["姓名", "总分", "平均分"]].head(3)
# 整理所有分析结果
analysis_result = {
"各科指标": subject_analysis,
"排序后数据": df_sorted,
"总分前3": top3_students,
"全班平均分": round(df["平均分"].mean(), 1),
"全班总分最高": df["总分"].max(),
"全班总分最低": df["总分"].min()
}
logging.info("成绩数据分析完成")
# 打印关键结果
print("\n" + "="*50)
print("📊 成绩分析核心结果")
print("="*50)
print(f"全班平均分:{analysis_result['全班平均分']}")
print(f"全班总分最高:{analysis_result['全班总分最高']}({df[df['总分']==df['总分'].max()]['姓名'].iloc[0]})")
print(f"全班总分最低:{analysis_result['全班总分最低']}({df[df['总分']==df['总分'].min()]['姓名'].iloc[0]})")
print("\n🏆 总分前3名:")
print(analysis_result["总分前3"])
return analysis_result
# 继续在main函数中调用分析函数
if __name__ == "__main__":
score_df = read_score_data("student_scores.xlsx")
if score_df is not None:
analysis_result = analyze_score_data(score_df)
运行后会输出核心分析结果,类似:
==================================================
📊 成绩分析核心结果
==================================================
全班平均分:84.5
全班总分最高:461(小丽)
全班总分最低:383(小强)
🏆 总分前3名:
姓名 总分 平均分
0 小丽 461 92.2
1 小明 463 92.6
2 小芳 441 88.2
步骤4:可视化(生成3类图表)
分析结果用文字展示不够直观,我们用matplotlib生成3类图表:
- 各科平均分柱状图:对比各科难度;
- 学生总分折线图:展示学生成绩分布;
- 各科及格率饼图:直观看到及格情况。
def plot_score_visualization(analysis_result, df):
"""
生成成绩可视化图表(柱状图、折线图、饼图)
参数:analysis_result - 分析结果字典,df - 排序后的DataFrame
"""
logging.info("开始生成可视化图表")
subjects = ["语文", "数学", "英语", "物理", "化学"]
# 1. 图1:各科平均分柱状图(对比各科难度)
plt.figure(figsize=(10, 6)) # 设置图表大小(宽10,高6)
avg_scores = [analysis_result["各科指标"][subj]["平均分"] for subj in subjects]
bars = plt.bar(subjects, avg_scores, color=['#FF6B6B', '#4ECDC4', '#45B7D1', '#96CEB4', '#FECA57'])
# 在柱子上添加数值标签
for bar, score in zip(bars, avg_scores):
plt.text(bar.get_x() + bar.get_width()/2, bar.get_height() + 0.5,
str(score), ha='center', va='bottom', fontsize=10)
plt.title("各科平均分对比", fontsize=14, pad=20) # 标题
plt.xlabel("科目", fontsize=12) # x轴标签
plt.ylabel("平均分", fontsize=12) # y轴标签
plt.ylim(0, 100) # y轴范围(0-100,符合分数逻辑)
plt.grid(axis='y', alpha=0.3) # 添加y轴网格线(透明效果)
plt.savefig("各科平均分柱状图.png", dpi=300, bbox_inches='tight') # 保存图片(高清300dpi)
plt.close() # 关闭当前图表,避免重叠
logging.info("已生成:各科平均分柱状图.png")
# 2. 图2:学生总分折线图(展示成绩分布)
plt.figure(figsize=(10, 6))
student_names = df["姓名"].tolist()
student_totals = df["总分"].tolist()
plt.plot(student_names, student_totals, marker='o', linewidth=2, markersize=8, color='#FF6B6B')
# 在每个点上添加总分标签
for name, total in zip(student_names, student_totals):
plt.text(student_names.index(name), total + 2, str(total),
ha='center', va='bottom', fontsize=9)
plt.title("学生总分排名分布", fontsize=14, pad=20)
plt.xlabel("学生姓名", fontsize=12)
plt.ylabel("总分", fontsize=12)
plt.grid(True, alpha=0.3)
plt.xticks(rotation=45) # 姓名标签旋转45度,避免重叠
plt.savefig("学生总分折线图.png", dpi=300, bbox_inches='tight')
plt.close()
logging.info("已生成:学生总分折线图.png")
# 3. 图3:各科及格率饼图(直观展示及格情况)
plt.figure(figsize=(10, 8))
pass_rates = [analysis_result["各科指标"][subj]["及格率(%)"] for subj in subjects]
# 设置饼图颜色
colors = ['#FF6B6B', '#4ECDC4', '#45B7D1', '#96CEB4', '#FECA57']
# 突出显示及格率最高的科目(explode参数,0.1表示向外突出)
explode = [0.1 if rate == max(pass_rates) else 0 for rate in pass_rates]
# 绘制饼图(autopct显示百分比,保留1位小数)
wedges, texts, autotexts = plt.pie(
pass_rates,
labels=subjects,
colors=colors,
explode=explode,
autopct='%1.1f%%',
startangle=90, # 饼图起始角度
textprops={'fontsize': 11}
)
plt.title("各科及格率分布", fontsize=14, pad=20)
plt.axis('equal') # 保证饼图是正圆形
plt.savefig("各科及格率饼图.png", dpi=300, bbox_inches='tight')
plt.close()
logging.info("已生成:各科及格率饼图.png")
print("\n✅ 所有可视化图表已生成完成!")
print("生成的图片文件:")
print("1. 各科平均分柱状图.png")
print("2. 学生总分折线图.png")
print("3. 各科及格率饼图.png")
# 完整main函数:读取→分析→可视化
if __name__ == "__main__":
print("="*60)
print("📋 Python学生成绩数据分析与可视化工具")
print("="*60)
# 1. 读取数据
score_df = read_score_data("student_scores.xlsx")
if score_df is not None:
# 2. 分析数据
analysis_result = analyze_score_data(score_df)
# 3. 生成可视化图表
plot_score_visualization(analysis_result, analysis_result["排序后数据"])
print("\n🎉 程序执行完毕!")
三、实战成果与拓展
1. 查看实战成果
运行完整代码后,你会获得:
- 日志输出:记录每一步操作(读取数据、分析、绘图),方便排查问题;
- 文字分析结果:全班平均分、总分排名、各科指标等关键信息;
- 3张可视化图表:保存在项目文件夹中,可直接用于汇报或展示(高清300dpi)。
2. 功能拓展(自己动手试试)
学会基础后,可尝试添加以下功能,巩固知识点:
- 新增“不及格学生提醒”:在分析函数中,筛选出各科不及格的学生,打印提醒;
- 支持CSV文件输入:修改
read_score_data函数,用pd.read_csv()读取CSV格式数据; - 生成分析报告:用
open()函数创建TXT文件,将分析结果写入,生成完整报告。
总结
这篇实战项目串联了前九篇的核心知识点:
- 基础语法:循环(计算各科指标)、条件判断(及格率统计);
- 函数封装:将读取、分析、绘图拆分为独立函数,代码更易维护;
- 异常处理:捕获文件不存在、格式错误等异常,程序更健壮;
- 模块导入:使用
pandas(第三方库)处理数据,matplotlib(第三方库)绘图; - 面向对象(可选):若想进一步优化,可将“分析工具”封装成类(如
ScoreAnalyzer),提升代码复用性。
至此,“Python从入门到实战”系列基础篇已全部完成!接下来你可以根据兴趣深入学习——比如用requests做爬虫、用Django开发Web、用TensorFlow做AI,Python的生态非常丰富,只要打好基础,后续学习会更轻松~
更多推荐

所有评论(0)