Python中的员工轮换名册

问题描述 投票:1回答:2

我正在为我的团队编写轮班名册。考虑,有“ a”个高级主管(一个位置很少,而在另一个位置很少),“ b”个团队负责人(一个位置很少,而另一个位置很少),“ c”个值班经理(很少一个)位置和其他位置)。我想为他们在python中创建一个班次名册。

条件如下。

  1. 日期范围为2002年1月1日至2020年12月31日。

  2. 将有3个班次,我需要在3个班次中容纳a + b + c资源(〜相等)

  3. 每个班次应具有1个主要资源和1个辅助资源。
  4. 由于这是每周一次的班次,因此资源应重新分配。假设在第1周的班次中a1是主要的,而a2是次要的,则在第2周的第二周中a2应该是主要的,而a1应该是次要的,依此类推。 (我觉得这部分很困难)感谢任何帮助。

每天进行迭代时,如何为每个班次(主要和次要)选择资源?

典型名册应如下所示。

typical roster should look like this

感谢您的任何帮助。

提前感谢

这是我的实现方式。请参见下面的代码并进行说明。

导入声明

import pandas as pd
import datetime as dt
from datetime import datetime
import random

输入要为其准备期间清单的开始日期和结束日期

start_date = dt.date(2020,6,1)
end_date = dt.date(2020,12,31)

创建数据框

roster=pd.DataFrame(columns=['Date',
                            'Week Number',
                             'Day',
                           'INDIA SHIFT 1 PRIMARY',
                           'INDIA SHIFT 1 Secondary',
                           'INDIA SHIFT 2 PRIMARY',
                           'INDIA SHIFT 2 Secondary',
                           'US SHIFT PRIMARY',
                           'US SHIFT SECONDARY',
                           'Weekend On-call Primary',
                           'Weekend On-call Secondary',
                           'Duty Manager 1',
                           'Duty Manager 2',
                           'Duty Manager Weekend'])

用日期,周号,工作日向DF填充

required_date = []
week_no = []
weekday = []

daterange = pd.date_range(start_date, end_date)
for single_date in daterange:
    required_date.append(single_date.strftime("%Y-%m-%d"))
    week_no.append(single_date.isocalendar()[1])
    weekday.append(single_date.strftime("%A"))

roster['Date'] = required_date
roster['Week Number'] = week_no
roster['Day'] = weekday   

我当前的DF看起来像这样enter image description here

然后我正在读取包含资源和假期的输入文件

Resources = pd.read_excel('Input_Data.xlsx', sheet_name='Resources')
Holidays = pd.read_excel('Input_Data.xlsx', sheet_name='Holidays')

资源和假日DF看起来像这样enter image description here

然后,我正在优化假期并删除空值

Holidays.India = Holidays.India.astype(str)
Holidays.US = Holidays.US.astype(str)
Holidays.US = Holidays.US.apply(lambda x : None if x=='NaT' else x)
US_holidays = list(filter(None,list(Holidays.US)))
IND_holidays = list(Holidays.India)

然后,我将明智的假日和普通假日分隔开来>

# segregate holidays whether common holiday or region wise
def Optimize_IND_Holidays(IND_holidays):
    for i in IND_holidays:
        if(i < roster['Date'][0]):
            IND_holidays.remove(i)
            return Optimize_IND_Holidays(IND_holidays)
Optimize_IND_Holidays(IND_holidays)

def Optimize_US_Holidays(US_holidays):
    for i in US_holidays:
        if(i < roster['Date'][0]):
            US_holidays.remove(i)
            return Optimize_US_Holidays(US_holidays)
Optimize_US_Holidays(US_holidays)

common_holidays = []
for i in IND_holidays:
    for j in US_holidays:
        if i == j:
            common_holidays.append(i)
            IND_holidays.remove(i)
            US_holidays.remove(i)

common_holidays,IND_holidays , US_holidays

基于位置分离资源,因为当一个位置度假时,其他位置资源应转移。

IND_Res = list(Resources.IND) + list(Resources.TL)
US_Res = list(Resources.US)
US_Res, IND_Res

现在这是我遇到的问题,尽管这是一个临时解决方案,但这并不理想,并且无法实时工作。我在这里所做的是,由于每个班次只有2个资源(偶数和奇数周),所以我也选择分配1个TL,每个班次分配1个高级。除非有假期或周末,否则每周都会有值班经理。我在这里明确分配。因此,我需要一个代码/想法,该如何使用python隐式实现它,而不是手动分配并记住条件编号4。

# get week numbers as list
weekno = list(roster['Week Number'])
shift1 = {}
shift2 = {}
shift3 = {}
# make a set from the week numbers list and sort them to iterate
for i in sorted(list(set(weekno))):
    if(int(i)%2==0):
        shift1.update({i:[Resources.TL[0],Resources.IND[0]]})
        shift2.update({i:[Resources.TL[1],Resources.IND[1]]})
        shift3.update({i:[Resources.US[0],Resources.US[1]]})
    else:
        shift1.update({i:[Resources.TL[1],Resources.IND[1]]})
        shift2.update({i:[Resources.TL[0],Resources.IND[0]]})
        shift3.update({i:[Resources.US[1],Resources.US[0]]})        

周末工作人员清单

weekend_Resources = list(Resources.IND)+list(Resources.US)
weekend_Managers = list(Resources.DutyManager)+list(Resources.TL)
weekend_combinations = [[a, b] for a in weekend_Resources  
          for b in weekend_Managers if a != b]

我在这里分配工作日和周末的资源,而不分配给假期。

IND_shift1_prim = []
IND_shift1_sec = []
IND_shift2_prim = []
IND_shift2_sec = []
US_shift_prim = []
US_shift_sec = []
Duty1 = []
Duty2 = []
Weekend_prim = []
Weekend_sec = []
for j in sorted(list(set(weekno))):
    r1 = random.randint(0,len(weekend_combinations)-1)
    for i in range(len(roster)):
        if((roster['Week Number'][i]==j) and ((roster['Day'][i] != 'Saturday') and (roster['Day'][i] != 'Sunday'))):
            #print(roster['Date'][i],roster['Week Number'][i])
            IND_shift1_prim.append(shift1[j][0])
            IND_shift1_sec.append(shift1[j][1])
            IND_shift2_prim.append(shift2[j][0])
            IND_shift2_sec.append(shift2[j][1])
            US_shift_prim.append(shift3[j][0])
            US_shift_sec.append(shift3[j][1])
            Duty1.append(Resources.DutyManager[0])
            Duty2.append(Resources.DutyManager[1])
            Weekend_prim.append("")
            Weekend_sec.append("")
        if((roster['Week Number'][i]==j) and ((roster['Day'][i] == 'Saturday') or (roster['Day'][i] == 'Sunday'))):
            IND_shift1_prim.append("")
            IND_shift1_sec.append("")
            IND_shift2_prim.append("")
            IND_shift2_sec.append("")
            US_shift_prim.append("")
            US_shift_sec.append("")
            Duty1.append("")
            Duty2.append("")
            Weekend_prim.append(weekend_combinations[r1][0])
            Weekend_sec.append(weekend_combinations[r1][1])

对于假期资源分配,下面是代码。

# for IND, US common holidays


for i in range(len(roster)):
    which_day = datetime.strptime((roster['Date'][i]),"%Y-%m-%d").strftime('%A')
    if (which_day != 'Saturday' and which_day != 'Sunday'):
        for j in range(len(common_holidays)):
            if(roster['Date'][i] == common_holidays[j]):
                r1 = random.randint(0,len(US_Res)-1)
                r2 = random.randint(0,len(IND_Res)-1)
                IND_shift1_prim[i] = IND_Res[r2]
                IND_shift1_sec[i] = US_Res[r1]
                IND_shift2_prim[i] = IND_Res[r2]
                IND_shift2_sec[i] = US_Res[r1]
                US_shift_prim[i] = US_Res[r1]
                US_shift_sec[i] = IND_Res[r2]
        # for India holidays
        for i in range(len(roster)):
            for j in range(len(IND_holidays)):
                if(roster['Date'][i] == IND_holidays[j]):
                    r1 = random.sample(range(0,len(US_Res)),2)
                    IND_shift1_prim[i] = US_Res[r1[0]]
                    IND_shift1_sec[i] = US_Res[r1[1]]
                    IND_shift2_prim[i] = US_Res[r1[1]]
                    IND_shift2_sec[i] = US_Res[r1[0]]
                    US_shift_prim[i] = US_Res[r1[0]]
                    US_shift_sec[i] = US_Res[r1[1]]
                    Duty1[i] = Resources.DutyManager[0]
                    Duty2[i] = Resources.DutyManager[0]

        #for US holidays
        for i in range(len(roster)):
            for j in range(len(US_holidays)):
                if(roster['Date'][i] == US_holidays[j]):
                    r1 = random.sample(range(0,len(IND_Res)),2)
                    IND_shift1_prim[i] = IND_Res[r1[0]]
                    IND_shift1_sec[i] = IND_Res[r1[1]]
                    IND_shift2_prim[i] = IND_Res[r1[1]]
                    IND_shift2_sec[i] = IND_Res[r1[0]]
                    US_shift_prim[i] = IND_Res[r1[0]]
                    US_shift_sec[i] = IND_Res[r1[1]]
                    Duty1[i] = Resources.DutyManager[1]
                    Duty2[i] = Resources.DutyManager[1]                    

然后我对照DataFrame本身的长度检查了每个列表的长度,以确保它们相等。

# make sure length of each list is same as number of total days for which roster is being prepared
len(IND_shift1_prim),len(IND_shift1_sec),len(IND_shift2_prim),len(IND_shift2_sec),len(US_shift_prim),len(US_shift_sec),len(Duty1),len(Duty2),len(roster)

然后我将列表分配给数据框的列。

roster['INDIA SHIFT 1 PRIMARY'] = IND_shift1_prim
roster['INDIA SHIFT 1 Secondary'] = IND_shift1_sec
roster['INDIA SHIFT 2 PRIMARY'] = IND_shift2_prim
roster['INDIA SHIFT 2 Secondary'] = IND_shift2_sec
roster['US SHIFT PRIMARY'] = US_shift_prim
roster['US SHIFT SECONDARY'] = US_shift_sec
roster['Duty Manager 1'] = Duty1
roster['Duty Manager 2'] = Duty2
roster['Weekend On-call Primary'] = Weekend_prim
roster['Weekend On-call Secondary'] = Weekend_sec

最后将数据框导出到excel。

with pd.ExcelWriter('roster.xlsx') as writer:
    June_roster.T.to_excel(writer, sheet_name = 'June')
    July_roster.T.to_excel(writer, sheet_name = 'July')
    August_roster.T.to_excel(writer, sheet_name = 'August')
    Sep_roster.T.to_excel(writer, sheet_name = 'September')
    Oct_roster.T.to_excel(writer, sheet_name = 'October')
    Nov_roster.T.to_excel(writer, sheet_name = 'November')
    Dec_roster.T.to_excel(writer, sheet_name = 'December')

最终数据框看起来像这样enter image description here

这是我到目前为止所做的。请问有人建议如何将条件4编码为keeipng吗?]

我正在为我的团队编写轮班名册。考虑,有“ a”个前辈(一个位置很少,而另一个位置很少),“ b”个团队负责人(一个位置很少,而另一个位置很少),“ c” ...

python shift
2个回答
0
投票
我在工作日一直使用这种逻辑

0
投票
最后我自己做的...........
© www.soinside.com 2019 - 2024. All rights reserved.