使用Python Pandas计算连续或并行任务的实际持续时间

b5buobof  于 2023-02-02  发布在  Python
关注(0)|答案(2)|浏览(133)

我有一个多行的panda数据框。每行中有一个对象和在某台机器上加工的持续时间(有开始时间和结束时间)。每个对象可以在几台机器上连续加工。我需要找到所有作业的实际持续时间。例如:
| 对象|机器|T启动|T端|
| - ------|- ------|- ------|- ------|
| 1个|A类|十七点二十六分|十七点五十七分|
| 1个|乙|十七点二十六分|十八点三十三分|
| 1个|C级|十八点五十六分|十九点四十六分|
| 第二章|A类|14点整|15点整|
| 第二章|C级|十四点半|15点整|
| 三个|A类|十二点整|十二点半|
| 三个|C级|13点整|十三点四十五分|
对象1的实际持续时间是117分钟,对象2是60分钟,对象3是75分钟。我尝试使用groupby,计算每个对象的进程持续时间之和以及最小值和最大值,即第一个开始和最后一个结束。然后我编写了一个函数来比较这些值 但它不适用于对象1,它适用于对象2和3。以下是我的解决方案:
| 对象|最小值|最大值|和T|LT_实际|
| - ------|- ------|- ------|- ------|- ------|
| 1个|十七点二十六分|十九点四十六分|一百四十八|140错误!|
| 第二章|14点整|15点整|九十|六十好!|
| 三个|十二点整|十三点四十五分|七十五|75好!|

def calc_lead_time(min_t_start, max_t_end, t_sum):
    t_max_min = (max_t_end - min_t_start) / pd.Timedelta(minutes=1)
    if t_max_min <= t_sum:
        return t_max_min
    else:
        return t_sum
    
df['LT_ACTUAL'] = df.apply(lambda x : calc_lead_time(x['min'], x['max'], x['sumT']), axis=1)

我发布了一张图片来解释所有的情况。我需要计算任务之间的实际持续时间

cu6pst1q

cu6pst1q1#

假设数据按开始时间排序,并且一个任务工期不完全在另一个任务工期内,则可以使用:

start = pd.to_timedelta(df['T start']+':00')
end = pd.to_timedelta(df['T end']+':00')

s = start.groupby(df['Object']).shift(-1)

(end.mask(end.gt(s), s).sub(start)
    .groupby(df['Object']).sum()
)

输出:

Object
1   0 days 01:57:00
2   0 days 01:00:00
3   0 days 01:15:00
dtype: timedelta64[ns]

对于分钟:

start = pd.to_timedelta(df['T start']+':00')
end = pd.to_timedelta(df['T end']+':00')

s = start.groupby(df['Object']).shift(-1)

(end.mask(end.gt(s), s).sub(start)
    .groupby(df['Object']).sum()
    .dt.total_seconds().div(60)
)

输出:

Object
1    117.0
2     60.0
3     75.0
dtype: float64
处理重叠间隔

有关重叠间期分组的逻辑,请参见here

(df.assign(
        start=pd.to_timedelta(df['T start']+':00'),
        end=pd.to_timedelta(df['T end']+':00'),
        max_end=lambda d: d.groupby('Object')['end'].cummax(),
        group=lambda d: d['start'].ge(d.groupby('Object')['max_end'].shift()).cumsum()
    )
   .groupby(['Object', 'group'])
   .apply(lambda g: g['end'].max()-g['start'].min())
   .groupby(level='Object').sum()
   .dt.total_seconds().div(60)
)

输出:

Object
1    117.0
2     60.0
3     75.0
4     35.0
dtype: float64

使用的输入:

Object Machine T start  T end
0       1       A   17:26  17:57
1       1       B   17:26  18:33
2       1       C   18:56  19:46
3       2       A   14:00  15:00
4       2       C   14:30  15:00
5       3       A   12:00  12:30
6       3       C   13:00  13:45
7       4       A   12:00  12:30
8       4       C   12:00  12:15
9       4       D   12:20  12:35
9rnv2umw

9rnv2umw2#

def function1(dd:pd.DataFrame):
    col1=dd.apply(lambda ss:pd.date_range(ss["T start"]+pd.to_timedelta("1 min"),ss["T end"],freq="min"),axis=1).explode()
    min=col1.min()-pd.to_timedelta("1 min")
    max=col1.max()
    sumT=col1.size
    LT_ACTUAL=col1.drop_duplicates().size

    return pd.DataFrame({"min":min.strftime('%H:%M'),"max":max.strftime('%H:%M'),"sumT":sumT,"LT_ACTUAL":LT_ACTUAL,},index=[dd.name])

df1.groupby('Object').apply(function1).droplevel(0)

输出:

min    max  sumT  LT_ACTUAL
1  17:26  19:46   148        117
2  14:00  15:00    90         60
3  12:00  13:45    75         75

相关问题