摘要:本文介绍了如何使用 Python 编写一个自动值班安排的脚本。该脚本会读取可值班人员名单、初始化每个人的值班次数、生成值班安排,并将结果写入 Excel 文件。本教程适用于需要安排值班人员的场景,如公司、学校等。
一、需求分析
值班表生成器需要满足以下主要需求:
- 输入:从Excel文件中读取每天可值班的人员名单。(本文的代码实现按照星期几来划分每天的可以值班人员)
- 平衡性:确保每个人的值班次数相对平均,避免偏向某个人值班次数过多。
- 随机性:避免简单的循环排班,使值班表具有一定的随机性。
- 可扩展性:能够适应不同的人员名单和值班次数要求。
二、所需工具与材料
Python 3.x
pandas 库
Excel 文件(用于存储值班安排和值班次数)
三、程序实现
我们使用Python编程语言,并使用pandas库来读取和写入Excel文件。以下是值班表生成器的实现步骤:
-
读取可值班人员名单:定义一个read_avail_persons(day)函数,从指定的Excel文件中读取每天可值班的人员名单。
-
初始化值班次数:定义一个init_duty_count(persons)函数,根据所有可值班人员的列表,创建一个初始值班次数字典,每个人的值班次数初始化为0。
-
获取当前值班次数最少的人员:定义一个get_least_duty_person(persons, duty_count)函数,根据值班次数字典和可值班人员列表,选择当前值班次数最少的人员进行值班安排。在有多个人员值班次数相同时,从中随机选择一个人员。
-
更新值班次数:定义一个update_duty_count(person, duty_count)函数,将被选中的人员的值班次数加一。
-
排班操作:在主函数中,根据每天可值班人员名单和值班次数要求进行排班操作。我们使用一个嵌套循环,外层循环控制排班的周期(如一周或两周),内层循环控制每天有多少人值班。在每次循环中,选择当前值班次数最少的人员进行值班安排,并更新值班次数。
-
写入排班结果:定义一个write_schedule(schedule)函数,将生成的值班表写入Excel文件。
四、运行和结果
1. 导入所需库
import pandas as pd
import random
2. 读取可值班人员名单
# 读取可值班人员名单
def read_avail_persons(day):
filename = f"{day}Night.xlsx"
df = pd.read_excel(filename)
return list(df.iloc[:, 0])
3. 初始化每个人的值班次数为 0
# 初始化每个人的值班次数为0
def init_duty_count(persons):
return {person: 0 for person in persons}
4. 获取当前值班次数最少的人员
# 获取当前值班次数最少的人员
def get_least_duty_person(persons, duty_count):
least_duty = min(duty_count[person] for person in persons)
least_duty_persons = [person for person in persons if duty_count[person] == least_duty]
return random.choice(least_duty_persons)
5. 更新值班次数
# 更新值班次数
def update_duty_count(person, duty_count):
duty_count[person] += 1
6. 写入排班结果到 Excel 文件
# 写入排班结果到 Excel 文件
def write_schedule(schedule):
df = pd.DataFrame(schedule)
df.to_excel("schedule.xlsx", index=False)
7. 写入值班次数到 Excel 文件
# 写入值班次数到 Excel 文件
def write_duty_count(duty_count):
df = pd.DataFrame.from_dict(duty_count, orient='index', columns=['Duty Count'])
df.index.name = 'Person'
df.to_excel("duty_count.xlsx")
8. 主函数
# 主函数
def main():
days = ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"]
schedule = {day: {} for day in days}
# 读取可值班人员名单
avail_persons = {day: read_avail_persons(day) for day in days}
all_persons = list(set([person for persons in avail_persons.values() for person in persons]))
# 初始化值班次数
duty_count = init_duty_count(all_persons)
# 排班
for week in range(2): # 排两周的班
for day in days:
avail_persons_day = avail_persons[day]
for _ in range(9): # 每天有9个人值班
least_duty_person = get_least_duty_person(avail_persons_day, duty_count)
schedule[day][(week * 9) + _ + 1] = least_duty_person
update_duty_count(least_duty_person, duty_count)
# 写入排班结果
write_schedule(schedule)
# 写入值班次数
write_duty_count(duty_count)
if __name__ == "__main__":
main()
运行值班表生成器,获取生成的值班表Excel文件。您可以根据实际需求调整Excel文件的格式和数据。生成的值班表将确保每人值班次数的平衡分配,并具备一定的随机性。
全部代码:
import pandas as pd
import random
# 读取可值班人员名单
def read_avail_persons(day):
filename = f"{day}Night.xlsx"
df = pd.read_excel(filename)
return list(df.iloc[:, 0])
# 初始化每个人的值班次数为0
def init_duty_count(persons):
return {person: 0 for person in persons}
# 获取当前值班次数最少的人员
def get_least_duty_person(persons, duty_count):
least_duty = min(duty_count[person] for person in persons)
least_duty_persons = [person for person in persons if duty_count[person] == least_duty]
return random.choice(least_duty_persons)
# 更新值班次数
def update_duty_count(person, duty_count):
duty_count[person] += 1
# 写入排班结果到 Excel 文件
def write_schedule(schedule):
df = pd.DataFrame(schedule)
df.to_excel("schedule.xlsx", index=False)
# 写入值班次数到 Excel 文件
def write_duty_count(duty_count):
df = pd.DataFrame.from_dict(duty_count, orient='index', columns=['Duty Count'])
df.index.name = 'Person'
df.to_excel("duty_count.xlsx")
# 主函数
def main():
days = ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"]
schedule = {day: {} for day in days}
# 读取可值班人员名单
avail_persons = {day: read_avail_persons(day) for day in days}
all_persons = list(set([person for persons in avail_persons.values() for person in persons]))
# 初始化值班次数
duty_count = init_duty_count(all_persons)
# 排班
for week in range(2): # 排两周的班
for day in days:
avail_persons_day = avail_persons[day]
for _ in range(9): # 每天有9个人值班
least_duty_person = get_least_duty_person(avail_persons_day, duty_count)
schedule[day][(week * 9) + _ + 1] = least_duty_person
update_duty_count(least_duty_person, duty_count)
# 写入排班结果
write_schedule(schedule)
# 写入值班次数
write_duty_count(duty_count)
if __name__ == "__main__":
main()
总结:
使用Python编程语言和pandas库,我们可以轻松地实现一个值班表生成器。这个程序能够根据指定的人员名单和值班次数要求,快速生成一份平衡的值班表。值班表生成器在许多需要连续安排固定工作时间的场景下具有重要的应用价值,帮助组织节省时间和人力成本。
感谢阅读本文,希望对您了解值班表生成器有所帮助!