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

使用Pandas进行Timestamp过滤:筛选员工可执行的潜在班次

解决DataFrame班次与可用时间的冲突筛选问题

你的需求是移除df1中所有无法完全落在员工可用时段(df2)内的潜在班次,也就是保留那些班次的开始时间晚于等于某个可用时段的开始,且结束时间早于等于该可用时段结束的行。

先分析你之前尝试的问题:df1[df1.starts_at[0] >= df2.starts_at]这个写法有几个明显问题:

  • 只拿了df1中第一个班次的开始时间来比较,没有遍历所有班次;
  • 仅比较了开始时间,没校验结束时间是否在可用时段内;
  • df1和df2长度不同,这样的布尔序列无法正确筛选df1的行。

下面给出两种可行的解决方案:

方法1:通过交叉合并+筛选实现

这种方法先建立两个DataFrame的笛卡尔积,然后筛选出符合条件的班次,最后去重得到结果:

import pandas as pd
from pandas import Timestamp

# 构造你的数据
n1 = {'starts_at': {0: Timestamp('2019-06-02 09:00:00'), 1: Timestamp('2019-06-02 17:00:00'), 2: Timestamp('2019-06-02 14:00:00'), 3: Timestamp('2019-06-03 09:30:00')}, 'ends_at': {0: Timestamp('2019-06-02 17:00:00'), 1: Timestamp('2019-06-02 22:30:00'), 2: Timestamp('2019-06-02 22:30:00'), 3: Timestamp('2019-06-03 13:00:00')}}
n2 = {'starts_at': {0: Timestamp('2019-06-01 14:00:00'), 1: Timestamp('2019-06-01 14:41:32.464000'), 2: Timestamp('2019-06-01 15:00:00'), 3: Timestamp('2019-06-02 10:00:00'), 4: Timestamp('2019-06-02 14:00:00'), 5: Timestamp('2019-06-02 17:00:00'), 6: Timestamp('2019-06-02 17:30:00'), 7: Timestamp('2019-06-03 17:00:00')}, 'ends_at': {0: Timestamp('2019-06-01 22:30:00'), 1: Timestamp('2019-06-01 22:32:44.862000'), 2: Timestamp('2019-06-01 22:30:00'), 3: Timestamp('2019-06-02 18:30:00'), 4: Timestamp('2019-06-03 00:00:00'), 5: Timestamp('2019-06-03 00:00:00'), 6: Timestamp('2019-06-02 21:00:00'), 7: Timestamp('2019-06-03 23:00:00')}}
df1 = pd.DataFrame(n1)
df2 = pd.DataFrame(n2)

# 给df1添加唯一标识,方便后续筛选
df1['shift_id'] = df1.index

# 交叉合并两个表,得到所有班次与可用时段的组合
merged = df1.merge(df2, how='cross')

# 筛选出完全包含在可用时段内的班次
valid_mask = (merged['starts_at_x'] >= merged['starts_at_y']) & (merged['ends_at_x'] <= merged['ends_at_y'])
valid_shifts = merged[valid_mask]['shift_id'].unique()

# 得到最终有效班次
result = df1[df1['shift_id'].isin(valid_shifts)].drop('shift_id', axis=1)
print(result)

方法2:使用apply逐行校验

这种方法更直观,对df1的每一行检查是否存在df2中的可用时段能完全包含它:

import pandas as pd
from pandas import Timestamp

# 构造数据(同上)
n1 = {'starts_at': {0: Timestamp('2019-06-02 09:00:00'), 1: Timestamp('2019-06-02 17:00:00'), 2: Timestamp('2019-06-02 14:00:00'), 3: Timestamp('2019-06-03 09:30:00')}, 'ends_at': {0: Timestamp('2019-06-02 17:00:00'), 1: Timestamp('2019-06-02 22:30:00'), 2: Timestamp('2019-06-02 22:30:00'), 3: Timestamp('2019-06-03 13:00:00')}}
n2 = {'starts_at': {0: Timestamp('2019-06-01 14:00:00'), 1: Timestamp('2019-06-01 14:41:32.464000'), 2: Timestamp('2019-06-01 15:00:00'), 3: Timestamp('2019-06-02 10:00:00'), 4: Timestamp('2019-06-02 14:00:00'), 5: Timestamp('2019-06-02 17:00:00'), 6: Timestamp('2019-06-02 17:30:00'), 7: Timestamp('2019-06-03 17:00:00')}, 'ends_at': {0: Timestamp('2019-06-01 22:30:00'), 1: Timestamp('2019-06-01 22:32:44.862000'), 2: Timestamp('2019-06-01 22:30:00'), 3: Timestamp('2019-06-02 18:30:00'), 4: Timestamp('2019-06-03 00:00:00'), 5: Timestamp('2019-06-03 00:00:00'), 6: Timestamp('2019-06-02 21:00:00'), 7: Timestamp('2019-06-03 23:00:00')}}
df1 = pd.DataFrame(n1)
df2 = pd.DataFrame(n2)

# 定义校验函数:检查当前班次是否被某个可用时段完全包含
def is_valid_shift(row):
    return ((df2['starts_at'] <= row['starts_at']) & (df2['ends_at'] >= row['ends_at'])).any()

# 筛选有效班次
result = df1[df1.apply(is_valid_shift, axis=1)]
print(result)

结果说明

两种方法都会得到相同的有效班次:

starts_at             ends_at
1 2019-06-02 17:00:00 2019-06-02 22:30:00
2 2019-06-02 14:00:00 2019-06-02 22:30:00

这符合你的需求:移除了索引0(上午班次早于可用时间)和索引3(次日上午班次早于当日可用时段开始时间)的冲突班次。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.14 08:33:17