You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用Pandas按动态24小时间隔为DataFrame时间列分配组值?

问题描述

现有如下Pandas DataFrame,其中列B为datetime类型数据:

import pandas as pd

data = {'A': ['XYZ', 'XYZ', 'XYZ', 'XYZ', 'PQR', 'PQR', 'PQR', 'PQR', 'CVB', 'CVB', 'CVB', 'CVB'], 
        'B': ['2022-02-16 14:00:31', '2022-02-16 16:11:26', '2022-02-16 17:31:26', '2022-02-16 22:47:46', '2022-02-17 07:11:11', '2022-02-17 10:43:36', '2022-02-17 15:05:11', '2022-02-18 18:06:12', '2022-02-19 09:05:46', '2022-02-19 13:02:16', '2022-02-19 18:05:26', '2022-02-19 22:05:26']}
df = pd.DataFrame(data)
df['B'] = pd.to_datetime(df['B'])

需求为按动态24小时间隔分组:第一个组的起始时间为数据集首个时间戳,后续数据若在该起始时间的24小时范围内则归为同一组;若超出范围则开启新组,新组起始时间设为当前数据的时间,以此类推,最终生成Group列。预期输出如下:

ABGroup
0XYZ2022-02-16 14:00:311
1XYZ2022-02-16 16:11:261
2XYZ2022-02-16 17:31:261
3XYZ2022-02-16 22:47:461
4PQR2022-02-17 07:11:111
5PQR2022-02-17 10:43:361
6PQR2022-02-17 15:05:112
7PQR2022-02-18 18:06:123
8CVB2022-02-19 09:05:463
9CVB2022-02-19 13:02:163
10CVB2022-02-19 18:05:263
11CVB2022-02-19 22:05:264

当前尝试的代码仅标记了第一个组,其余组值为NaN,无法满足需求。

解决方案

方案1:Numba加速循环(高效处理百万级数据)

该方案通过Numba编译循环逻辑,将Python循环转换为机器码执行,在处理百万级时间戳时性能优异,避免了纯Pandas操作的额外开销。

import pandas as pd
import numpy as np
from numba import jit

# 初始化数据
data = {'A': ['XYZ', 'XYZ', 'XYZ', 'XYZ', 'PQR', 'PQR', 'PQR', 'PQR', 'CVB', 'CVB', 'CVB', 'CVB'], 
        'B': ['2022-02-16 14:00:31', '2022-02-16 16:11:26', '2022-02-16 17:31:26', '2022-02-16 22:47:46', '2022-02-17 07:11:11', '2022-02-17 10:43:36', '2022-02-17 15:05:11', '2022-02-18 18:06:12', '2022-02-19 09:05:46', '2022-02-19 13:02:16', '2022-02-19 18:05:26', '2022-02-19 22:05:26']}
df = pd.DataFrame(data)
df['B'] = pd.to_datetime(df['B'])

# 将时间转换为纳秒数值,方便Numba处理
timestamps = df['B'].values.astype(np.int64)
# 24小时对应的纳秒数
one_day_ns = pd.Timedelta(days=1).value

@jit(nopython=True)
def assign_groups(timestamps):
    n = len(timestamps)
    groups = np.ones(n, dtype=np.int64)
    current_group_start = timestamps[0]
    current_group = 1
    for i in range(1, n):
        if timestamps[i] > current_group_start + one_day_ns:
            current_group += 1
            current_group_start = timestamps[i]
        groups[i] = current_group
    return groups

# 生成Group列
df['Group'] = assign_groups(timestamps)
print(df)

方案2:纯Pandas矢量化实现(无需额外依赖)

如果不想引入Numba依赖,可使用Pandas的扩展窗口操作实现,虽效率略低于Numba方案,但也能处理大规模数据:

import pandas as pd

# 初始化数据
data = {'A': ['XYZ', 'XYZ', 'XYZ', 'XYZ', 'PQR', 'PQR', 'PQR', 'PQR', 'CVB', 'CVB', 'CVB', 'CVB'], 
        'B': ['2022-02-16 14:00:31', '2022-02-16 16:11:26', '2022-02-16 17:31:26', '2022-02-16 22:47:46', '2022-02-17 07:11:11', '2022-02-17 10:43:36', '2022-02-17 15:05:11', '2022-02-18 18:06:12', '2022-02-19 09:05:46', '2022-02-19 13:02:16', '2022-02-19 18:05:26', '2022-02-19 22:05:26']}
df = pd.DataFrame(data)
df['B'] = pd.to_datetime(df['B'])

# 初始化组起始时间序列
group_starts = pd.Series(index=df.index, dtype='datetime64[ns]')
group_starts.iloc[0] = df['B'].iloc[0]

# 判断每个位置是否需要开启新组
new_group = df['B'] > group_starts.expanding().max() + pd.Timedelta(days=1)
# 更新组起始时间:新组用当前时间,旧组沿用之前的起始时间
group_starts = group_starts.where(~new_group, df['B'])

# 生成Group列:新组标志的累积和+1
df['Group'] = new_group.cumsum() + 1
print(df)

核心逻辑说明

两种方案遵循同一逻辑:

  1. 第一个组的起始时间为数据集的首个时间戳
  2. 遍历每个时间戳,若当前时间超出当前组起始时间的24小时范围,则开启新组,新组起始时间设为当前时间
  3. 通过累积计数生成最终组号

内容的提问来源于stack exchange,提问作者user3046211

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.16 09:41:03