如何使用Pandas查找任务的链接序列?

2024-09-30 22:20:13 发布

您现在位置:Python中文网/ 问答频道 /正文

让我们假设这3个数据帧带有“Start”和“Start”某项任务的结束日期

Task1 = pd.DataFrame({"Start": pd.date_range("1-jan-2021", periods=10**3, freq="1H")}).assign(
    End=lambda d: d.Start + pd.Timedelta(hours=20))

Task2 = pd.DataFrame({"Start": pd.date_range("10-jan-2021", periods=500, freq="3H")}).assign(
    End=lambda d: d.Start + pd.Timedelta(hours=24))

Task3 = pd.DataFrame({"Start": pd.date_range("5-jan-2021", periods=700, freq="2H")}).assign(
    End=lambda d: d.Start + pd.Timedelta(hours=16))

durations = [20,24,16]
names = ['Task1', 'Task2', 'Task3']
nbr_of_tasks = 3

我正在寻找一种方法,将任务[x]的每个“结束日期”与任务[x+1]的“开始日期”等链接起来。。。 目前,我只能找到Task_x['End']==Task_x+1['Start'],其中x是任务编号的序列。以下代码是我想到的:

list_dfs = [Task1,Task2,Task3]
rev_list_dfs = list(reversed(list_dfs))
comparaison_dates = list(rev_list_dfs[0]['Start'])
rev_list_dfs = rev_list_dfs[1:len(rev_list_dfs)]
print(comparaison_dates)

for element in rev_list_dfs:     
    inception = element.loc[element['End'].isin(comparaison_dates)].reset_index(drop=True)
    if inception.empty :
        print('No available slots for the chosen interval')        
        break
    else :
        comparaison_dates = inception['Start']

miccheck = []
for element in names:
    miccheck.append(pd.DataFrame(columns=[f'{element}_Start', f'{element}_End'])) 

for i in range(0,nbr_of_tasks):
    miccheck[i][f'{names[i]}_Start'] = comparaison_dates + pd.to_timedelta(sum(durations[:i]), unit='h')
    miccheck[i][f'{names[i]}_End'] = comparaison_dates + pd.to_timedelta(sum(durations[:i+1]), unit='h')
    

excell = pd.concat(miccheck, axis=1).reset_index(drop=True)
print('\n       Start & end date of each sequence       \n')
print(excell)

我如何找到任务之间有停机时间的连续任务?我所说的停机时间是指在执行下一个任务之前等待的时间。我不是特别想找一个虚构的答案,只是给我指出正确的方向会很有帮助。先谢谢你

编辑:

期望输出: enter image description here


Tags: dataframedatenamesrevrangeelementstartlist
1条回答
网友
1楼 · 发布于 2024-09-30 22:20:13

关键思想是使用merge_asof。对于两个任务数据帧,以下将为Task1中的每一行找到Task2中的行,其中End_1Start_2彼此最接近(但仍然End_1 <= Start_2):

pd.merge_asof(
    Task1.rename(columns=lambda c: c + "_1"),
    Task2.rename(columns=lambda c: c + "_2"), 
    left_on="End_1", 
    right_on="Start_2", 
    direction="forward",
)

以下函数将此思想应用于任意数量的任务数据帧,并计算待机时间:

def merge_task_dfs(dfs):
    dfs = [df.rename(columns=lambda c: c + f"_{i+1}") for i, df in enumerate(dfs)]
    
    output = dfs[0]
    
    for i, df in enumerate(dfs[1:]):
        i += 1
        output = pd.merge_asof(
            output,
            df,
            left_on=f"End_{i}",
            right_on=f"Start_{i+1}",
            direction="forward",
        ).assign(**{f"StandBy_{i}_{i+1}": lambda d: d[f"Start_{i+1}"] - d[f"End_{i}"]})
        
    return output

它可以应用于提供的示例数据,如下所示:

Task1 = pd.DataFrame({"Start": pd.date_range("1-jan-2021", periods=10**3, freq="1H")}).assign(
    End=lambda d: d.Start + pd.Timedelta(hours=20))

Task2 = pd.DataFrame({"Start": pd.date_range("10-jan-2021", periods=500, freq="3H")}).assign(
    End=lambda d: d.Start + pd.Timedelta(hours=24))

Task3 = pd.DataFrame({"Start": pd.date_range("5-jan-2021", periods=700, freq="2H")}).assign(
    End=lambda d: d.Start + pd.Timedelta(hours=16))

df = merge([Task1, Task2, Task3])

输出的前5行是: enter image description here

相关问题 更多 >