Python中不用loc查找DataFrame用户输入值及课表分析问题求助
课程表处理作业问题及解决方案
需求与问题
- 作业限制:仅使用pandas、numpy和基础Python
- 数据源:含5个工作表(周一至周五)的Excel课程表
- 核心问题:
- 禁用
loc函数时,如何根据用户输入课程匹配对应时间、日期、教室信息 - 如何找出整周最空闲的时段(行)
- 禁用
- 需完成7项任务:
- Pandas读取课表
- 删除不必要的首行
- 单门课程查询:返回所有场次的时间、日期、教室编号
- 多课程查询:返回指定课程列表的所有场次信息
- 查询指定日期的空闲时段
- 找出整周使用频率最低的教室
- 找出整周最繁忙的实验室名称
现有代码(查找功能失效)
import pandas as pd import numpy as np # 读取Excel文件 path = (r'C:\Users\user\Downloads\TimeTable, FSC, Fall-2022.xlsx') data = pd.read_excel(path,sheet_name=None) df = pd.concat(data[frame] for frame in data.keys()) # 分别读取每日工作表 mon = pd.read_excel(path,sheet_name = "Monday") tues = pd.read_excel(path,sheet_name = "Tuesday") wed = pd.read_excel(path,sheet_name = "Wednesday") thur = pd.read_excel(path,sheet_name = "Thursday") fri = pd.read_excel(path,sheet_name = "Friday") # 构建每日表字典 timetable = { "Monday" : mon, "Tuesday" : tues, "Wednesday" : wed, "Thursday" : thur, "Friday" : fri, } # 删除各表前2行(索引1、2) mon.drop([1,2], axis = 0, inplace = True) tues.drop([1,2], axis = 0, inplace = True) wed.drop([1,2], axis = 0, inplace = True) thur.drop([1,2], axis = 0, inplace = True) fri.drop([1,2], axis = 0, inplace = True) mon.head() # 失效的查找代码 df.loc[df[timetable(['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday'])==subject]] df.loc[df["Monday"]==subject] # 用户输入课程名 subject = str(input("Enter the subject you want to search classes for: "))
问题分析与修复方案
1. 禁用loc时的课程查询实现
原代码错误点:
- 错误将字典
timetable当作函数调用,语法错误 subject变量定义在查找代码之后,导致未定义- 合并表时未保留日期维度,无法区分课程所属日期
替代实现(不使用loc):
# 先获取用户输入 subject = input("输入要查询的课程名称:").strip() results = [] # 遍历每日表筛选匹配课程 for day, daily_df in timetable.items(): # 重置索引避免行号混乱 daily_df = daily_df.reset_index(drop=True) # 布尔索引筛选课程(假设课程名在第2列,根据你的表结构调整) match_mask = daily_df.iloc[:, 1] == subject # 遍历匹配行,收集信息 for _, row in daily_df[match_mask].iterrows(): results.append({ '日期': day, '时间': row.iloc[0], # 假设时间在第1列 '教室编号': row.iloc[2] # 假设教室在第3列 }) # 输出结果 print(pd.DataFrame(results))
2. 查找最空闲的时段(行)
统计每行的课程数量,数量最少的行即为最空闲时段:
# 合并所有每日表并添加日期列 merged_data = [] for day, daily_df in timetable.items(): daily_df['日期'] = day merged_data.append(daily_df) full_timetable = pd.concat(merged_data, ignore_index=True) # 统计每行的非空课程数(假设课程列从第2列到倒数第2列) full_timetable['课程数'] = full_timetable.iloc[:, 1:-1].notna().sum(axis=1) # 筛选课程数最少的行 min_course_count = full_timetable['课程数'].min() free_slots = full_timetable[full_timetable['课程数'] == min_course_count] print("最空闲的时段:") print(free_slots[[full_timetable.columns[0], '日期']])
全任务整合代码
import pandas as pd import numpy as np def load_and_clean_timetable(file_path): """读取并清理所有工作表:删除前2行,返回每日表字典""" sheets = pd.read_excel(file_path, sheet_name=None) cleaned_timetable = {} for day, df in sheets.items(): # 删除索引1、2的行,重置索引 cleaned_df = df.drop([1, 2], axis=0).reset_index(drop=True) cleaned_timetable[day] = cleaned_df return cleaned_timetable def search_single_course(timetable, course_name): """查询单门课程的所有场次信息""" results = [] for day, df in timetable.items(): # 按实际列位置调整,示例:课程在第2列,时间在第1列,教室在第3列 match_mask = df.iloc[:, 1] == course_name for _, row in df[match_mask].iterrows(): results.append({ '日期': day, '时间': row.iloc[0], '课程': course_name, '教室编号': row.iloc[2] }) return pd.DataFrame(results) def search_course_list(timetable, course_list): """查询多门课程的所有场次信息""" all_results = [] for course in course_list: course_results = search_single_course(timetable, course.strip()) all_results.extend(course_results.to_dict('records')) return pd.DataFrame(all_results) def get_free_time_slots(timetable, target_day): """获取指定日期的空闲时段""" df = timetable[target_day] time_col = df.columns[0] # 筛选所有课程列都为空的行(课程列从第2列开始) free_mask = df.iloc[:, 1:].isna().all(axis=1) # 不使用loc,直接用布尔索引+列名 return df[free_mask][time_col].tolist() def get_least_used_classroom(timetable): """找出整周使用频率最低的教室""" room_usage = {} for day, df in timetable.items(): # 假设教室在第3列 rooms = df.iloc[:, 2].dropna().tolist() for room in rooms: room_usage[room] = room_usage.get(room, 0) + 1 min_usage = min(room_usage.values()) return [room for room, cnt in room_usage.items() if cnt == min_usage] def get_busiest_lab(timetable): """找出整周最繁忙的实验室(假设名称含'Lab')""" lab_usage = {} for day, df in timetable.items(): rooms = df.iloc[:, 2].dropna().tolist() for room in rooms: if 'Lab' in str(room): # 根据实际实验室命名规则调整 lab_usage[room] = lab_usage.get(room, 0) + 1 max_usage = max(lab_usage.values()) return [lab for lab, cnt in lab_usage.items() if cnt == max_usage] # 主程序执行 if __name__ == "__main__": file_path = r'C:\Users\user\Downloads\TimeTable, FSC, Fall-2022.xlsx' timetable = load_and_clean_timetable(file_path) # 任务3:单课程查询 single_course = input("请输入要查询的课程名称:").strip() print("\n单课程查询结果:") print(search_single_course(timetable, single_course)) # 任务4:多课程查询 course_input = input("\n请输入要查询的课程列表(逗号分隔):").strip() course_list = course_input.split(',') print("\n多课程查询结果:") print(search_course_list(timetable, course_list)) # 任务5:指定日期空闲时段 target_day = input("\n请输入要查询的日期(如Monday/Tuesday):").strip() print(f"\n{target_day}的空闲时段:") print(get_free_time_slots(timetable, target_day)) # 任务6:使用频率最低的教室 print("\n整周使用频率最低的教室:") print(get_least_used_classroom(timetable)) # 任务7:最繁忙的实验室 print("\n整周最繁忙的实验室:") print(get_busiest_lab(timetable))
关键注意事项
- 所有列的位置(课程列、时间列、教室列)需根据你的Excel表实际结构调整,代码中为示例位置
- 若严格禁用
loc,所有筛选操作均使用布尔索引直接操作DataFrame(如df[mask][col]) - 实验室匹配规则需根据实际命名调整(示例中用'Lab'关键字匹配)
内容的提问来源于stack exchange,提问作者Maryam
相关产品推荐
相关产品推荐

