【问题标题】:Python dividing time intervals into hourly buckets inPython将时间间隔划分为每小时的桶
【发布时间】:2019-06-10 20:41:12
【问题描述】:

我有一个如下数据集,其中每个 ID 都可以在任何给定时间和持续时间签入和签出

            ID  checkin_datetime    checkout_datetime
            4   04-01-2019 13:07    04-01-2019 13:09
            4   04-01-2019 13:09    04-01-2019 13:12
            4   04-01-2019 14:06    04-01-2019 14:07
            4   04-01-2019 14:55    04-01-2019 15:06
            22  04-01-2019 20:23    04-01-2019 21:32
            22  04-01-2019 21:38    04-01-2019 21:42
            25  04-01-2019 23:22    04-02-2019 00:23
            29  04-02-2019 01:00    04-02-2019 06:15

由此计算的签到分钟数需要划分为下表所示的每小时存储桶,以便我可以按小时计算每个 Id 跨小时和天的累计总数,即使签到签出发生在跨小时和天天。

帮助表示赞赏:)

            ID  checkin_datetime    checkout_datetime   day         HR  Minutes
            4   04-01-2019 13:07    04-01-2019 13:09    04-01-2019  13  2
            4   04-01-2019 13:09    04-01-2019 13:12    04-01-2019  13  3
            4   04-01-2019 14:06    04-01-2019 14:07    04-01-2019  14  1
            4   04-01-2019 14:55    04-01-2019 15:06    04-01-2019  14  5
            4   04-01-2019 14:55    04-01-2019 15:06    04-01-2019  15  6
            22  04-01-2019 20:23    04-01-2019 21:32    04-01-2019  20  27
            22  04-01-2019 20:23    04-01-2019 21:32    04-01-2019  21  32
            22  04-01-2019 21:38    04-01-2019 21:42    04-01-2019  21  4
            25  04-01-2019 23:22    04-02-2019 00:23    04-01-2019  23  28
            25  04-01-2019 23:22    04-02-2019 00:23    04-02-2019  0   23
            29  04-02-2019 01:00    04-02-2019 06:15    04-02-2019  1   60
            29  04-02-2019 01:00    04-02-2019 06:15    04-02-2019  2   60
            29  04-02-2019 01:00    04-02-2019 06:15    04-02-2019  3   60
            29  04-02-2019 01:00    04-02-2019 06:15    04-02-2019  4   60
            29  04-02-2019 01:00    04-02-2019 06:15    04-02-2019  5   60
            29  04-02-2019 01:00    04-02-2019 06:15    04-02-2019  6   15

创建数据框的代码:

data={'ID':[4,4,4,4,22,22,25,29],
  'checkin_datetime':['04-01-2019 13:07','04-01-2019 13:09','04-01-2019 14:06','04-01-2019 14:55','04-01-2019 20:23'
  ,'04-01-2019 21:38','04-01-2019 23:22','04-02-2019 01:00'],
  'checkout_datetime':['04-01-2019 13:09','04-01-2019 13:12','04-01-2019 14:07','04-01-2019 15:06','04-01-2019 21:32'
                       ,'04-01-2019 21:42','04-02-2019 00:23'
                       ,'04-02-2019 06:15']
}

df = DataFrame(data,columns= ['ID', 'checkin_datetime','checkout_datetime'])

df['checkout_datetime'] = pd.to_datetime(df['checkout_datetime'])
df['checkin_datetime'] = pd.to_datetime(df['checkin_datetime'])

【问题讨论】:

  • 如何计算小时和分钟列?
  • @JainilPatel 我已在用于创建数据框的代码中添加
  • @anky_91 时间戳的小时:所以在上面的例子中,22 04-01-2019 20:23 04-01-2019 21:32,小时是 20 小时(晚上 8 点)那个小时是 27 分钟,然后是 21 32 分钟,这就是我需要帮助的时间段
  • @Ani 04-01-2019 20:23 27 分钟怎么样?不应该是23吗?你想要结帐和签入之间的区别吗?请解释计算
  • @anky_91 我在粘贴输出时犯了错误,我遗漏了第二行,现在更正了 id 22 04-01-2019 20:23 04-01-2019 21:32 介于 2 之间晚上 8 点到晚上 9 点是第 20 小时的 27 分钟和第 21 小时的 32 分钟(两个小时之间总共有 59 分钟。

标签: python pandas data-structures data-manipulation


【解决方案1】:

很简单:
- 在此期间,您只需从签到中减去结帐(datetime 可以这样做)。
- 要在几分钟内得到它 - 将它除以一分钟的 timedelta(我将使用内置的 pandas)。
- 要从datetime 获取小时,请调用.hour,类似地.date() 获取日期(第一个是属性,第二个是方法 - 注意括号)。

df['Hour'] = df['checkin_datetime'].apply(lambda x: x.hour)
df['Date'] = df['checkin_datetime'].apply(lambda x: x.date())
df['duration'] = df['checkout_datetime']-df['checkin_datetime']
df['duration_in_minutes'] = (df['checkout_datetime']-df['checkin_datetime'])/pd.Timedelta(minutes=1)

[已编辑]:我有一个将持续时间分成几小时的解决方案,但这不是最优雅的...

df2 = pd.DataFrame(
index=pd.DatetimeIndex(
    start=df['checkin_datetime'].min(),
    end=df['checkout_datetime'].max(),freq='1T'),
    columns = ['is_checked_in','ID'], data=0)

for index, row in df.iterrows():
    df2['is_checked_in'][row['checkin_datetime']:row['checkout_datetime']] = 1
    df2['ID'][row['checkin_datetime']:row['checkout_datetime']] = row['ID']

df3 = df2.resample('1H').aggregate({'is_checked_in': sum,'ID':max})
df3['Hour'] = df3.index.to_series().apply(lambda x: x.hour)

【讨论】:

  • 这不能解决 id 29 的整个问题:29 04-02-2019 01:00 04-02-2019 06:15 它给了我这个 ID checkin_datetime checkout_datetime Logged_time Hour Date duration duration_in_minutes 29 2019-04-02 01:00:00 2019-04-02 06:15:00 315.0 1 2019-04-02 0 天 05:15:00.000000000 315.0 从凌晨 1 点到 315 分钟需要分成多个小时早上 6 点 15 分进入 6 个小时的时段,第一个 5 个有 60 分钟,最后一个有 15 分钟
  • 我如何获得这些带有 ID 以及所涉及的小时和日期的类似数据?
  • 非常相似(添加到答案中)。 “小时”部分只是一个 .apply,就像我之前向您展示过的那样,对于“ID”,我们将 .sum() 替换为更复杂的 .aggregate,它在每一列上的操作方式不同(ID 的总和将为一个问题,但不应该是最大 ID)。
  • 如何在这段代码中添加另一个级别,比如 zone_id 来对数据进行分组?
  • 我刚刚在stackoverflow.com/questions/56661066/…发布了新问题
【解决方案2】:
import pandas as pd

data={'ID':[4,4,4,4,22,22,25,29],
  'checkin_datetime':['04-01-2019 13:07','04-01-2019 13:09','04-01-2019 14:06','04-01-2019 14:55','04-01-2019 20:23'
  ,'04-01-2019 21:38','04-01-2019 23:22','04-02-2019 01:00'],
  'checkout_datetime':['04-01-2019 13:09','04-01-2019 13:12','04-01-2019 14:07','04-01-2019 15:06','04-01-2019 21:32'
                       ,'04-01-2019 21:42','04-02-2019 00:23'
                       ,'04-02-2019 06:15']
}

df = pd.DataFrame(data,columns= ['ID', 'checkin_datetime','checkout_datetime'])

df['checkout_datetime'] = pd.to_datetime(df['checkout_datetime'])
df['checkin_datetime'] = pd.to_datetime(df['checkin_datetime'])
df['Hour'] = df['checkin_datetime'].apply(lambda x: x.hour)
df['Date'] = df['checkin_datetime'].apply(lambda x: x.date())
df['duration'] = df['checkout_datetime']-df['checkin_datetime']
df['duration_in_minutes'] = (df['checkout_datetime']-df['checkin_datetime'])/pd.Timedelta(minutes=1)
with pd.option_context('display.max_rows', None, 'display.max_columns', None):  # more options can be specified also
    print(df)

我认为 Itamar Muskhkin 之前给出的答案是绝对正确的。

【讨论】:

  • 对于 id 29 04-02-2019 01:00 04-02-2019 06:15 上面的代码给了我 1 行,总登录时间在凌晨 1 点到 315 分钟。我需要将这 315 分钟分成从凌晨 1 点到凌晨 5 点的每小时存储桶,每个存储桶 60 分钟,以及早上 6 点的存储桶,每个存储桶 15 分钟
  • 所以不要在小时内写出 1,2,3,4,5,6,7,8。它就像几个小时过去了。
猜你喜欢
  • 2019-11-01
  • 1970-01-01
  • 2021-03-31
  • 2022-01-20
  • 2015-07-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-02-16
相关资源
最近更新 更多