You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用Python编写函数批量处理19个批次CSV文件的测验数据统计

批量处理多批次学生测验数据的思路与实现方法

看起来你已经搞定了单个批次的统计逻辑,现在要把这套流程自动化覆盖19个批次对吧?核心思路就是把重复的批次-测验统计逻辑封装成可复用函数,然后批量遍历所有批次文件,自动完成统计并填充到目标DataFrame里。下面是具体的步骤和代码实现:

1. 重构重复逻辑为可复用函数

你会发现处理quiz1和quiz2的逻辑几乎完全一致,只是用的测验文件不同。我们可以把这部分逻辑抽成一个函数,输入批次学生列表和测验数据,直接返回该批次该测验的所有统计结果(出勤数+各分数段计数)。

import pandas as pd
import numpy as np
import glob

def get_quiz_statistics(batch_students, quiz_data):
    """
    计算单个批次在某一场测验中的统计数据
    参数:
        batch_students: 批次学生DataFrame,需包含'Firstname'列
        quiz_data: 测验原始DataFrame,已预处理好分数和空值
    返回:
        包含noofpresent、各分数段计数的字典
    """
    # 筛选出该批次参加测验的学生
    batch_quiz = quiz_data[quiz_data['Firstname'].isin(batch_students['Firstname'])]
    
    # 统计出勤人数
    no_of_present = len(batch_quiz)
    
    # 统计各分数段人数
    stats = {
        'noofpresent': no_of_present,
        'lesserthan50': len(batch_quiz[batch_quiz['Grade/100.00'] < 50]),
        'between50and60': len(batch_quiz[(batch_quiz['Grade/100.00'] >= 50) & (batch_quiz['Grade/100.00'] < 60)]),
        'between60and70': len(batch_quiz[(batch_quiz['Grade/100.00'] >= 60) & (batch_quiz['Grade/100.00'] < 70)]),
        'between70and80': len(batch_quiz[(batch_quiz['Grade/100.00'] >= 70) & (batch_quiz['Grade/100.00'] < 80)]),
        'greaterthan80': len(batch_quiz[batch_quiz['Grade/100.00'] >= 80])
    }
    return stats

2. 预处理测验数据(仅需执行一次)

把quiz1和quiz2的加载、分数转换、空值处理抽出来,只做一次,避免重复IO操作:

# 定义文件路径
q1path = 'd:\\a2\\quiz\\quiz1.csv'
q2path = 'd:\\a2\\quiz\\quiz2.csv'
batch_dir = 'd:\\a2\\batchwiselist\\'

# 预处理quiz1数据
q1 = pd.read_csv(q1path, usecols=['Firstname', 'Grade/10.00', 'State'], na_values=['-', 'In progress', np.NaN])
q1.dropna(inplace=True)
q1['Grade/100.00'] = q1['Grade/10.00'] * 10  # 转换为百分制,重命名列更清晰

# 预处理quiz2数据
q2 = pd.read_csv(q2path, usecols=['Firstname', 'Grade/10.00', 'State'], na_values=['-', 'In progress', np.NaN])
q2.dropna(inplace=True)
q2['Grade/100.00'] = q2['Grade/10.00'] * 10

3. 批量遍历所有批次并填充统计DataFrame

首先生成包含所有批次的MultiIndex,然后用glob批量获取所有批次文件,遍历每个批次完成统计:

# 获取所有批次文件
batch_files = glob.glob(f'{batch_dir}*.csv')

# 生成所有批次名称(比如从1.csv提取'batch1')
batch_names = [f'batch{file.split("\\")[-1].split(".")[0]}' for file in batch_files]

# 创建空的统计DataFrame
idx = pd.MultiIndex.from_product([batch_names, ['quiz1', 'quiz2']], names=['Batch', 'Quiz'])
cols = ['noofpresent', 'lesserthan50', 'between50and60', 'between60and70', 'between70and80', 'greaterthan80']
statdf = pd.DataFrame('-', idx, cols)

# 遍历每个批次处理
for batch_file in batch_files:
    # 加载批次学生数据,统一列名
    batch_df = pd.read_csv(batch_file, usecols=['studentName', 'admissionNumber'])
    batch_df.rename(columns={'studentName': 'Firstname'}, inplace=True)
    
    # 提取批次名称(比如'9.csv' -> 'batch9')
    batch_num = batch_file.split("\\")[-1].split(".")[0]
    batch_name = f'batch{batch_num}'
    
    # 处理quiz1并填充statdf
    q1_stats = get_quiz_statistics(batch_df, q1)
    statdf.loc[(batch_name, 'quiz1'), :] = q1_stats
    
    # 处理quiz2并填充statdf
    q2_stats = get_quiz_statistics(batch_df, q2)
    statdf.loc[(batch_name, 'quiz2'), :] = q2_stats

# 查看最终结果
print(statdf)
# 可以保存到文件
# statdf.to_csv('d:\\a2\\quiz_statistics.csv')

关键细节说明

  • 文件名与批次名映射:通过拆分文件名提取批次号,确保自动匹配到statdf的MultiIndex
  • 分数区间边界:明确每个区间的开闭范围(比如>=50且<60对应between50and60),避免统计遗漏或重复
  • 性能优化:测验数据只加载预处理一次,减少磁盘IO开销;用isin替代merge,简化学生匹配逻辑

内容的提问来源于stack exchange,提问作者therion

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.14 07:05:43