解放教师双手:用python打造智能excel作业自动批改

2025-04-23 21:32:30 17点赞 133收藏 16评论

背景

前阵子,我的一个老同学无意中跟我聊起来她的工作内容中,需要使用大量的Excel,其中批改学生作业比较痛苦,需要逐个去看学生上交的Excel作业,然后再汇总得分,是一个枯燥又耗时的工作。

于是,我想到处理Excel,那么python中的pandas十分合适,评分的过程其实就是对比答案的文件和作业的文件是否一致,一致就算对,不一致就算错。此外,再增加上计分的功能,那么这个需求其实很简单。

实现 1.0版本

稍微整理了流程之后,很快第一版的代码就产出了,主要逻辑如下:

  1. 比较的逻辑

def compare_columns(df1, df2, columns_config): diff_scores = {} for col_letter, score in columns_config.items(): index = column_letter_to_index(col_letter) column1 = df1.iloc[:, index] column2 = df2.iloc[:, index] diff = (column1 != column2).astype(int) # 计算差异,不同为1,相同为0 total_score = diff.sum() * score # 计算总分 diff_scores[f'Column {col_letter} (分值:{score})'] = total_score return diff_scores

2. 保存比较结果

def create_comparison_result(file_name, scores): result_data = { 'File Name': file_name, 'Total Score': sum(scores.values()), } # 添加每列的分数 result_data.update(scores) return result_data

3. 用户输入需要比较的列

columns_config = {} print("n请输入需要比对的列和对应的分值") print("示例:输入 'L 0.1' 表示L列每个差异扣0.1分") print("输入空行结束配置") while True: try: line = input("n请输入列名和分值 (格式:列名 分值),或直接按Enter结束: ").strip() if not line: if columns_config: break print("请至少配置一个列!") continue parts = line.split() if len(parts) != 2: print("格式错误!请使用'列名 分值'的格式,例如:'L 0.1'") continue column, score = parts column = column.upper() score = float(score) if not column.isalpha(): print("列名必须是字母!") continue columns_config[column] = score print(f"已添加:{column}列,分值:{score}") except ValueError: print("分值必须是数字!") continue

使用问题

初版代码很快完成,但是在同学的使用过程中,发现了几个问题:

  1. 当需要计算分数的列比较多时,需要频繁的输入,比较费劲

  2. 如果需要计算分数的部分不是一整列时,现在的代码不能满足

  3. 需要安装python环境及对应的依赖库,门槛稍高

优化思路

针对如上几个问题,

  1. 需要重新设计对比的逻辑,可以支持多列,甚至是不规则的单元格进行对比

  2. 将整个工程打包成一个exe文件,无需额外安装环境

优化 1.1版本

首先,将逻辑拆分成需要用户来设计一个模板,用做评分依据,在这个模板中,只要被标记了背景色,即视为需要评分的单元格。这样的好处是,无需额外输入要评分的列(行),以及支持无规则的单元格

其次,不再使用windows下的cmd命令窗口,而是增加了对话框,选择文件、目录时更方便

最后,整个代码打包成一个单独的exe文件

  1. 比较的逻辑

def compare_sheets(self, standard_df: pd.DataFrame, submission_df: pd.DataFrame) -> pd.DataFrame: """ 比较两个DataFrame,返回差异矩阵(相同为0,不同为1) """ # 确保两个DataFrame大小一致 max_rows = max(len(standard_df), len(submission_df)) max_cols = max(len(standard_df.columns), len(submission_df.columns)) # 创建空的差异矩阵 diff_matrix = pd.DataFrame(0, index=range(max_rows), columns=range(max_cols), dtype=int) # 比较每个单元格 for i in range(max_rows): for j in range(max_cols): # 获取标准答案的值 std_val = standard_df.iloc[i, j] if i < len(standard_df) and j < len(standard_df.columns) else 0 # 获取提交作业的值 sub_val = submission_df.iloc[i, j] if i < len(submission_df) and j < len(submission_df.columns) else 0 # 处理空值 if pd.isna(std_val): std_val = 0 if pd.isna(sub_val): sub_val = 0 try: # 尝试数值比较 std_num = float(std_val) if str(std_val).strip() != '' else 0 sub_num = float(sub_val) if str(sub_val).strip() != '' else 0 if abs(std_num - sub_num) >= 0.01: diff_matrix.iloc[i, j] = 1 except (ValueError, TypeError): # 字符串比较 if str(std_val).strip() != str(sub_val).strip(): diff_matrix.iloc[i, j] = 1 return diff_matrix

2. 计算得分

def calculate_sheet_score(self, standard_df: pd.DataFrame, submission_df: pd.DataFrame, scoring_df: pd.DataFrame) -> Tuple[float, Dict]: """ 计算单个sheet的得分 """ # 获取差异矩阵 diff_matrix = self.compare_sheets(standard_df, submission_df) # 计算扣分(差异矩阵与评分矩阵相乘) deduction_matrix = diff_matrix * scoring_df total_deduction = deduction_matrix.sum().sum() # 收集扣分详情 deductions = {} for i in range(len(diff_matrix)): for j in range(len(diff_matrix.columns)): if diff_matrix.iloc[i, j] == 1: # 如果有差异 # 获取标准答案的值(如果存在) expected = standard_df.iloc[i, j] if i < len(standard_df) and j < len(standard_df.columns) else None # 获取提交作业的值(如果存在) submitted = submission_df.iloc[i, j] if i < len(submission_df) and j < len( submission_df.columns) else None # 获取扣分值(如果存在) points = scoring_df.iloc[i, j] if i < len(scoring_df) and j < len(scoring_df.columns) else 0 deductions[(i, j)] = { 'expected': expected if expected is not None else '未填写', 'submitted': submitted if submitted is not None else '未填写', 'points_deducted': points } return total_deduction, deductions

使用问题

这次的评分过程足够灵活,但是由于当时设计了几个目录及文件(答案的文件、评分标准的文件、学生作业的目录、评分结果的目录),导致很容易误操作。所以需要再次优化

优化 1.1.1版本

优化逻辑改为:

  1. 目录选择逻辑优化 让用户选择一次目录,自动检测该目录下是否有答案的文件以及评分标准的文件,如果检测到,让用户确认;没有检测到,则提示用户进行选择。并且在该目录下自动生成结果文件夹

  2. 用户体验优化 程序完成后,自动打开生成结果文件夹

至此,这个简单的需求,算是满足了老同学的全部使用要求,而且比较简洁

解放教师双手:用python打造智能excel作业自动批改


最后,有兴趣的同学可以下载试试看,附上仓库地址

angelyangw/Excel Score Tools


作者声明本文无利益相关,欢迎值友理性交流,和谐讨论~

展开 收起
16评论

  • 精彩
  • 最新
  • 作为家长我想说,你这东西有啥用,现在作业都是家长在批改

    校验提示文案

    提交
    大学的

    校验提示文案

    提交
    收起所有回复
  • 我想学习一起表格自动化的

    校验提示文案

    提交
    我不卖课的

    校验提示文案

    提交
    去b站搜索vba,我这两天在学习。比较简单

    校验提示文案

    提交
    还有8条回复
    收起所有回复
  • 她?有情况 [邪恶]

    校验提示文案

    提交
    你想多了 [尴尬]

    校验提示文案

    提交
    收起所有回复
  • 以下是被折叠的评论 查看
已折叠部分评论
展开
收起
提示信息

取消
确认
评论举报

相关文章推荐

更多精彩文章
更多精彩文章
最新文章 热门文章
133
扫一下,分享更方便,购买更轻松