经过前面九篇的学习,我们已经掌握了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 pandasimport matplotlib.pyplot as plt,不报错就是安装完成。

二、实战案例:学生成绩数据分析与可视化

我们的实战流程分为四步:

  1. 准备数据:用Excel创建学生成绩表;
  2. 读取数据:用pandas读取Excel文件,处理异常(如文件不存在);
  3. 统计分析:计算平均分、最高分、及格率等核心指标;
  4. 可视化:用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类图表:

  1. 各科平均分柱状图:对比各科难度;
  2. 学生总分折线图:展示学生成绩分布;
  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文件,将分析结果写入,生成完整报告。

总结

这篇实战项目串联了前九篇的核心知识点:

  1. 基础语法:循环(计算各科指标)、条件判断(及格率统计);
  2. 函数封装:将读取、分析、绘图拆分为独立函数,代码更易维护;
  3. 异常处理:捕获文件不存在、格式错误等异常,程序更健壮;
  4. 模块导入:使用pandas(第三方库)处理数据,matplotlib(第三方库)绘图;
  5. 面向对象(可选):若想进一步优化,可将“分析工具”封装成类(如ScoreAnalyzer),提升代码复用性。

至此,“Python从入门到实战”系列基础篇已全部完成!接下来你可以根据兴趣深入学习——比如用requests做爬虫、用Django开发Web、用TensorFlow做AI,Python的生态非常丰富,只要打好基础,后续学习会更轻松~

更多推荐