
本文介绍一种贪心算法策略,用于对含两个时间戳列的dataframe进行分组:每组内 timestamp1 和 timestamp2 的各自极差均不得超过4天,确保分组满足双重约束并最大化每组行数。
本文介绍一种贪心算法策略,用于对含两个时间戳列的dataframe进行分组:每组内 timestamp1 和 timestamp2 的各自极差均不得超过4天,确保分组满足双重约束并最大化每组行数。
在实际数据分析中,常需依据时间维度对记录进行逻辑分组,但当存在两个独立时间戳字段(如事件起始时间与结束时间、申请时间与审批时间等),且业务要求两字段在组内各自跨度均受限时,简单按单字段排序+滑动窗口或 pd.cut 均无法直接满足需求。本教程提供一种鲁棒、可复用的贪心分组方案:按时间顺序遍历数据,动态维护当前组的 timestamp1_min 和 timestamp2_min,一旦新行超出任一字段的 4 天容忍阈值,即开启新组。
✅ 核心逻辑说明
- 排序前提:必须先按 timestamp1 和/或 timestamp2 排序(本例采用自然顺序,隐含时间先后逻辑;若原始顺序无意义,建议统一按 timestamp1 升序排列以保证贪心有效性)。
-
双重约束检查:对每一行,同时验证:
- (当前 timestamp1 − 当前组首个 timestamp1) ≤ 4 天
- (当前 timestamp2 − 当前组首个 timestamp2) ≤ 4 天
- 贪心更新:任一条件不满足 → 新建组,并将当前行设为该组的“锚点”(即新的 start_timestamp1 / start_timestamp2)。
? 完整实现代码
import pandas as pd
# 构造示例数据
data = {
'timestamp1': ['2022-02-18', '2022-02-19', '2022-02-21', '2022-03-11', '2022-03-12', '2022-03-30'],
'timestamp2': ['2023-01-02', '2023-01-04', '2023-01-11', '2024-02-05', '2024-02-06', '2024-02-07']
}
df = pd.DataFrame(data)
df['timestamp1'] = pd.to_datetime(df['timestamp1'])
df['timestamp2'] = pd.to_datetime(df['timestamp2'])
# 贪心分组函数(支持双重时间戳约束)
def assign_dual_timestamp_groups(df, max_days=4):
if df.empty:
return []
groups = []
current_group = 1
# 初始化首行为第一组锚点
start_t1 = df.iloc[0]['timestamp1']
start_t2 = df.iloc[0]['timestamp2']
for _, row in df.iterrows():
t1_diff = (row['timestamp1'] - start_t1).days
t2_diff = (row['timestamp2'] - start_t2).days
# 任一时间戳跨度超限 → 新组
if t1_diff > max_days or t2_diff > max_days:
current_group += 1
start_t1 = row['timestamp1']
start_t2 = row['timestamp2']
groups.append(current_group)
return groups
# 应用分组
df['group'] = assign_dual_timestamp_groups(df)
print(df[['timestamp1', 'timestamp2', 'group']])
输出结果:
timestamp1 timestamp2 group 0 2022-02-18 2023-01-02 1 1 2022-02-19 2023-01-04 1 2 2022-02-21 2023-01-11 2 3 2022-03-11 2024-02-05 3 4 2022-03-12 2024-02-06 3 5 2022-03-30 2024-02-07 4
⚠️ 关键注意事项
- 排序敏感性:该算法结果依赖于输入顺序。若原始数据无时间先后含义,务必先执行 df.sort_values(['timestamp1', 'timestamp2'], ignore_index=True),否则分组可能非最优甚至违反约束。
- 边界处理:.days 属性自动向下取整(如 1.9 days → 1),若需严格 ≥4.0 天才触发分组,可用 (row['t'] - start_t) >= pd.Timedelta(days=max_days) 替代。
- 扩展性:函数支持自定义 max_days 参数,便于适配不同业务场景(如7天滚动归档、30分钟会话分组等)。
- 性能提示:对超大数据集(>100万行),纯 Python 循环可能较慢;可考虑使用 numba.jit 加速,或改写为向量化逻辑(需结合 cummax/diff 等技巧,但复杂度显著上升)。
此方法以清晰的逻辑、最小的依赖和良好的可解释性,精准解决了双时间戳联合约束下的分组问题,是生产环境中值得信赖的基础工具模式。











