
本文介绍如何基于 Pass_ID 分组后,精准筛选出全部时间戳均落在指定时段(如 10:00–13:00)内的组,或仅提取在该时段内出现过的唯一 Pass_ID,兼顾简洁性与逻辑严谨性。
本文介绍如何基于 `pass_id` 分组后,精准筛选出**全部时间戳均落在指定时段(如 10:00–13:00)内**的组,或仅提取**在该时段内出现过的唯一 pass_id**,兼顾简洁性与逻辑严谨性。
在实际时间序列分析中,常需按业务标识(如 Pass_ID)分组,并进一步按“一天中的时间段”进行条件过滤。Pandas 提供了 between_time 方法,但其直接作用于 DataFrame 索引(且要求索引为 datetime 类型),因此需合理配合 set_index、groupby 和 filter 实现不同粒度的筛选目标。
✅ 场景一:提取「至少有一个记录落在指定时段内」的 Pass_ID(宽松匹配)
这是最常用的需求——只要某 Pass_ID 的任意一条记录发生在 10:00–13:00,就将其纳入结果:
# 确保 Date_Time 列为 datetime 类型(若尚未转换)
df["Date_Time"] = pd.to_datetime(df["Date_Time"])
# 设置 Date_Time 为索引,应用 between_time,再提取 Pass_ID 并去重
pass_ids_in_window = df.set_index("Date_Time").between_time("10:00", "13:00")["Pass_ID"].unique()
print(pass_ids_in_window) # 输出: ['B']
⚠️ 注意:between_time 默认包含边界(即 10:00:00 和 13:00:00 均被包含),且对时区不敏感;若数据含时区信息,建议先统一为本地时间或 UTC 再操作。
✅ 场景二:提取「所有记录均严格落在指定时段内」的 Pass_ID(严格匹配)
该逻辑要求某 Pass_ID 对应的所有时间点都满足 10:00 ≤ time ≤ 13:00,适用于质量控制或合规性校验:
result = (
df.groupby("Pass_ID")
.filter(lambda x: len(x.set_index("Date_Time").between_time("10:00", "13:00")) == len(x))
["Pass_ID"]
.unique()
)
print(result) # 输出: ['B']
此写法通过 filter 遍历每个 Pass_ID 子集:对子集设索引后调用 between_time,若返回行数等于原子集行数,则说明该组全部时间均在窗口内。
? 更健壮的替代写法(推荐用于生产环境)
为避免 lambda 中重复索引设置及潜在性能问题,可改用向量化方式预计算小时属性:
# 添加 hour 列(更直观、可复用)
df["hour"] = df["Date_Time"].dt.hour
# 严格匹配:每组的最小和最大 hour 都在 [10, 13] 范围内(注意:13:00 包含,13:59:59 也属 13 小时)
mask_strict = df.groupby("Pass_ID")["hour"].agg(["min", "max"]).apply(
lambda row: 10 <p>该方法无需反复设置索引,支持链式操作,且便于扩展(例如加入分钟级判断 df["Date_Time"].dt.time 或使用 pd.IntervalIndex)。</p><h3>✅ 总结</h3>
- between_time 是专为时间索引设计的高效工具,务必确保索引为 datetime 类型;
- groupby(...).filter(...) 适合逻辑复杂的组级筛选,但注意其内部会复制数据,大数据集下需评估性能;
- 预计算 dt.hour/dt.time 属性更适合多条件组合或需要复用时间特征的场景;
- 实际应用中,请始终验证 Date_Time 列是否已正确解析为 datetime64[ns],可使用 df["Date_Time"].dtype 检查。











