使用pandas计算时间范围内的阻塞时间

2024-09-28 05:27:51 发布

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

我有一份生产的产品或完成的过程清单,如下所示:

^{tb1}$

我想做的是计算在给定时间范围内没有产品/流程发生的时间量,例如从15:00到16:00,更具体地说,每天。 输出可以是“未发生任何事情的空闲分钟数/时间”或“空闲时间百分比”

import pandas as pd
import datetime
df = pd.read_csv('example_data.csv')

# generate list of products
listOfProducts = df['NAME'].drop_duplicates().tolist()

# define timeframe for each day
startTime = datetime.time(15, 0)
stopTime = datetime.time(16, 0)

# define daterange to look for
startDay = datetime(2021, 1, 1)
stopDay = datetime(2021,1, 5)


# do it for  every product
for i in listOfProducts:

    # filter dataframe by product
    df_product = df[df['NAME'] == i]
    
    # sort dataframe by start
    df_product  = df_product.sort_values(by='started')

    # ... how to proceed?

所需的输出应如下所示或类似:

^{tb2}$

以下是一些重要的注意事项:

  • 产品的时间范围可以相互重叠,在这种情况下,它们只能“计数一次”
  • 产品的时间范围可能与边界重叠(在这种情况下为15:00或16:00),在这种情况下,应计算边界内的时间

我很难以一种简单的方式实现它,因为这种边界情况使我无法计算时间增量。 在过去,我通过从这里逐行迭代并添加分钟或秒来解决这个问题。但我相信还有一种更简单的方法,可能是使用.groupby()函数


Tags: csvnameimportdffordatetimeby产品
1条回答
网友
1楼 · 发布于 2024-09-28 05:27:51

输入数据:

>>> df
        Name               Start                Stop
0  Product 1 2021-01-01 14:49:00 2021-01-01 15:04:00  # OK (overlap 4')
1  Product 1 2021-01-01 15:15:00 2021-01-01 15:37:00  # OK
2  Product 1 2021-01-01 15:30:00 2021-01-01 15:55:00  # OK
3  Product 1 2021-01-02 15:05:00 2021-01-02 15:22:00  # OK
4  Product 1 2021-01-03 15:45:00 2021-01-03 15:55:00  # OK
5  Product 1 2021-01-03 15:51:00 2021-01-03 16:23:00  # OK (overlap 9')
6  Product 1 2021-01-04 14:28:00 2021-01-04 17:12:00  # OK (overlap 60')
7  Product 1 2021-01-05 11:46:00 2021-01-05 13:40:00  # Out of bounds
8  Product 1 2021-01-05 17:20:00 2021-01-05 19:11:00  # Out of bounds

首先,将数据移出边界(7和8):

import datetime

START = datetime.time(15)
STOP = datetime.time(16)

df1 = df.loc[(df["Start"].dt.floor(freq="H").dt.time <= START)
              & (START <= df["Stop"].dt.floor(freq="H").dt.time),
             ["Start", "Stop"]]

提取StartStopdatetime的分钟数。如果进程在15:00之前开始,请设置为0,因为我们只希望保留重叠部分。如果进程在16:00后结束,请将分钟设置为59

import numpy as np

df1["m1"] = np.where(df1["Start"].dt.time > START, 
                     df1["Start"].sub(df1["Start"].dt.floor(freq="H"))
                                                  .dt.seconds // 60, 0)

df1["m2"] = np.where(df1["Stop"].dt.time < STOP,
                     df1["Stop"].sub(df1["Stop"].dt.floor(freq="H"))
                                                .dt.seconds // 60, 59)
>>> df1
                Start                Stop  m1  m2
0 2021-01-01 14:49:00 2021-01-01 15:04:00   0   4
1 2021-01-01 15:15:00 2021-01-01 15:37:00  15  37
2 2021-01-01 15:30:00 2021-01-01 15:55:00  30  55
3 2021-01-02 15:05:00 2021-01-02 15:22:00   5  22
4 2021-01-03 15:45:00 2021-01-03 15:55:00  45  55
5 2021-01-03 15:51:00 2021-01-03 16:23:00  51  59
6 2021-01-04 14:28:00 2021-01-04 17:12:00   0  59

创建一个空表len(df1)x60'以存储进程使用情况:

out = pd.DataFrame(0, index=df1.index, columns=pd.RangeIndex(60))

填充out数据帧:

for idx, (i1, i2) in df1[["m1", "m2"]].iterrows():
    out.loc[idx, i1:i2] = 1
>>> out
   0   1   2   3   4   5   6   ...  53  54  55  56  57  58  59
0   1   1   1   1   1   0   0  ...   0   0   0   0   0   0   0  # 4'
1   0   0   0   0   0   0   0  ...   0   0   0   0   0   0   0
2   0   0   0   0   0   0   0  ...   1   1   1   0   0   0   0
3   0   0   0   0   0   1   1  ...   0   0   0   0   0   0   0
4   0   0   0   0   0   0   0  ...   1   1   1   0   0   0   0
5   0   0   0   0   0   0   0  ...   1   1   1   1   1   1   1
6   1   1   1   1   1   1   1  ...   1   1   1   1   1   1   1  # full hour

[7 rows x 60 columns]

最后,计算空闲分钟数:

>>> 60 - (out.groupby(df1["Start"].dt.date).sum() & 1).sum(axis="columns")
Start
2021-01-01    22
2021-01-02    42
2021-01-03    50
2021-01-04     0
dtype: int64

注意:您必须确定Stop日期时间是否已关闭

相关问题 更多 >

    热门问题