一、实验目的:
(1)了解扩展库openpyxl的安装与使用。
(2)了解使用扩展库openpyxl操作Excel文件的方法。
(3)熟练运用字典结构解决实际问题。
二、实验内容:
假设某学校所有课程每学期允许多次考试,学生可随时参加考试,系统自动将每次成绩添加到Excel文件(包含3列:姓名,课程,成绩)中,现期末要求统计所有学生每门课程的最高成绩。
编写程序,模拟生成若干同学的成绩并写入Excel文件,其中学生姓名和课程名称均可重复,也就是允许出现同一门课程的多次成绩,最后统计所有学生每门课程的最高成绩,并写入新的Excel文件。
三、实验环境:
Windows 10/11 + Jupyter Notebook \ PyCharm \ Spyder \ VScode + Python 3.12、
四、实验结果:
(一)第一种方法:
from random import choice, randint from openpyxl import Workbook, load_workbook # 生成随机数据 def generateRandomInformation(filename): workbook = Workbook() worksheet = workbook.worksheets[0] worksheet.append(['姓名','课程','成绩']) # 中文名字中的第一、第二、第三个字 first = '赵钱孙李' middle = '伟昀琛东' last = '坤艳志' subjects = ('语文','数学','英语') for i in range(200): name = choice(first) # 按一定概率生成只有两个字的中文名字 if randint(1,100)>50: name = name + choice(middle) name = name + choice(last) # 依次生成姓名、课程名称和成绩 worksheet.append([name, choice(subjects), randint(0, 100)]) # 保存数据,生成Excel 2007格式的文件 workbook.save(filename) def getResult(oldfile, newfile): # 用于存放结果数据的字典 result = dict() # 打开原始数据 workbook = load_workbook(oldfile) worksheet = workbook.worksheets[0] # 遍历原始数据 for row in worksheet.rows: if row[0].value == '姓名': continue # 姓名,课程名称,本次成绩 name, subject, grade = map(lambda cell:cell.value, row) # 获取当前姓名对应的课程名称和成绩信息 # 如果result字典中不包含,则返回空字典 t = result.get(name, {}) # 获取当前学生当前课程的成绩,若不存在,返回0 f = t.get(subject, 0) # 只保留该学生该课程的最高成绩 if grade > f: t[subject] = grade result[name] = t workbook1 = Workbook() worksheet1 = workbook1.worksheets[0] worksheet1.append(['姓名','课程','成绩']) # 将result字典中的结果数据写入Excel文件 for name, t in result.items(): print(name, t) for subject, grade in t.items(): worksheet1.append([name, subject, grade]) workbook1.save(newfile) if __name__ == '__main__': oldfile = r'd:\test.xlsx' newfile = r'd:\result.xlsx' generateRandomInformation(oldfile) getResult(oldfile, newfile)
(二)第二种方法:
import pandas as pd
import numpy as np
# 模拟生成学生成绩数据
np.random.seed(0) # 为了结果的可重复性
num_students = 10 # 学生数量
num_courses = 5 # 课程数量
num_records = 100 # 记录数量
# 生成模拟数据
students = [f'学生{i}' for i in range(1, num_students + 1)]
courses = [f'课程{i}' for i in range(1, num_courses + 1)]
scores = np.random.randint(0, 101, size=num_records)
data = {
'姓名': np.random.choice(students, size=num_records),
'课程': np.random.choice(courses, size=num_records),
'成绩': scores
}
# 将数据写入Excel文件
df = pd.DataFrame(data)
df.to_excel('学生成绩.xlsx', index=False)
# 计算每个学生每门课程的最高成绩
max_scores = df.groupby(['姓名', '课程'])['成绩'].max().reset_index()
# 将最高成绩写入新的Excel文件
max_scores.to_excel('最高成绩.xlsx', index=False)
print("模拟数据已生成并写入'学生成绩.xlsx'")
print("最高成绩已计算并写入'最高成绩.xlsx'")
五、实验分析
第一段代码(使用pandas)
优点:
-
简洁性:使用
pandas
库可以更简洁地处理数据,特别是对于数据的分组和聚合操作。 -
效率:
pandas
在处理大型数据集时通常比手动循环更高效。 -
易读性:代码结构清晰,易于理解和维护。
-
功能强大:
pandas
提供了丰富的数据操作功能,方便进行复杂的数据处理。
缺点:
-
依赖性:需要安装
pandas
和openpyxl
库,对于没有这些库的环境需要额外的安装步骤。 -
内存使用:对于非常大的数据集,
pandas
可能会占用较多的内存。
第二段代码(使用openpyxl)
优点:
-
直接操作Excel:使用
openpyxl
可以直接对Excel文件进行读写操作,不需要转换为其他数据结构。 -
无需额外库:除了
openpyxl
,不需要其他数据处理库,对于只需要基本Excel操作的场景来说,这可能是一个优势。 -
灵活性:可以直接控制Excel的样式和格式,对于需要精细控制Excel输出格式的场景更为合适。
缺点:
-
代码冗余:对于数据处理,特别是聚合操作,代码较为冗长,不如
pandas
简洁。 -
效率问题:对于大型数据集,手动循环处理可能效率较低。
-
易错性:手动处理数据时,出错的概率更高,尤其是当逻辑变得复杂时。
总结
-
如果你关注代码的简洁性和处理大数据集的效率,第一段代码(使用
pandas
)可能是更好的选择。 -
如果你更关注对Excel文件的直接操作和格式控制,或者你的环境不允许安装额外的数据处理库,第二段代码(使用
openpyxl
)可能更适合你的需求。