基于Pandas的学生就近分配至限额学校问题求助
问题分析与代码修正
问题根源
原代码中错误添加了学校过滤条件:~df_distance_sorted['id_ecole'].isin(df_eleves['id_ecole']),该条件会把已有学生分配的学校全部排除,但实际逻辑是只要学校还有剩余名额,就可以继续接收学生。这个错误导致后续学生无法找到可分配的学校,仅完成了前5名学生的分配。
修正后的代码
import pandas as pd df_eleves = pd.DataFrame({ 'id_eleve' : [1,2,3,4,5,6,7,8,9] }) df_ecoles = pd.DataFrame({ 'id_ecole' : [1,2,3,4,5], 'places' : [2,4,3,1,2] }) # 新增已招生人数字段,满足需求要求 df_ecoles['inscrits'] = 0 df_distance = pd.DataFrame({ 'id_eleve' : [ 1,1,1,1,1,2,2,2,2,2,3,3,3,3,3,4,4,4,4,4, 5,5,5,5,5,6,6,6,6,6,7,7,7,7,7,8,8,8,8,8,9,9,9,9,9 ], 'id_ecole' : [ 1,2,3,4,5,1,2,3,4,5,1,2,3,4,5,1,2,3,4,5, 1,2,3,4,5,1,2,3,4,5,1,2,3,4,5,1,2,3,4,5,1,2,3,4,5 ], 'distance' : [ 20,30,15,9,8,55,100,73,42,4,15,88,32,3,25, 75,69,78,20,10,56,21,74,56,12,19,5,35,45,82, 13,75,63,14,9,1,14,98,20,6,48,65,32,147,65 ] }) # 按学生ID和距离升序排序,确保每个学生的学校列表是从近到远排列 df_distance_sorted = df_distance.sort_values(['id_eleve', 'distance']) # 初始化学生表的分配字段 df_eleves['id_ecole'] = None df_eleves['distance'] = None # 遍历每个学生进行分配 for index, row in df_eleves.iterrows(): id_eleve = row['id_eleve'] # 仅筛选当前学生的距离数据,移除错误的学校过滤条件 df_student_distances = df_distance_sorted[df_distance_sorted['id_eleve'] == id_eleve] # 按距离从近到远尝试分配学校 for _, school_row in df_student_distances.iterrows(): id_ecole = school_row['id_ecole'] # 检查学校剩余名额 if df_ecoles.loc[df_ecoles['id_ecole'] == id_ecole, 'places'].iloc[0] > 0: # 更新学生表的分配信息 df_eleves.at[index, 'id_ecole'] = id_ecole df_eleves.at[index, 'distance'] = school_row['distance'] # 更新学校表的剩余名额和已招生人数 df_ecoles.loc[df_ecoles['id_ecole'] == id_ecole, 'places'] -= 1 df_ecoles.loc[df_ecoles['id_ecole'] == id_ecole, 'inscrits'] += 1 break # 输出最终结果 print("学生分配结果:") print(df_eleves) print("\n学校招生状态:") print(df_ecoles)
修正说明
- 移除了错误的学校过滤逻辑,确保只要学校还有剩余名额,就可以被后续学生选择
- 新增了学校表的
inscrits字段,满足需求中记录已招生人数的要求 - 优化了变量命名,提升代码可读性
运行结果
学生分配结果:
id_eleve id_ecole distance 0 1 5 8 1 2 5 4 2 3 4 3 3 4 5 10 4 5 2 21 5 6 2 5 6 7 5 9 7 8 1 1 8 9 1 48
学校招生状态:
id_ecole places inscrits 0 1 0 2 1 2 2 2 2 3 3 0 3 4 0 1 4 5 0 4
内容的提问来源于stack exchange,提问作者Onyx
相关产品推荐
相关产品推荐

