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

如何不使用for循环,基于员工起止时间DataFrame切片客户交易DataFrame?

无需循环的高效时间区间筛选方案

当然有更高效的实现方式!我们可以利用Pandas的向量化特性和专门的区间索引工具,彻底摆脱Python循环带来的性能瓶颈,尤其适合处理大规模数据集。

核心思路

把所有工作时间区间整合成一个区间索引,然后直接检查客户交易时间是否落在任意一个区间内——全程都是Pandas内部优化的向量化操作,比循环快得多。

具体实现代码

import pandas as pd
from datetime import datetime

# 你的示例数据
customer_df = pd.DataFrame({'customer': ['A','B','C','A','D','E','K','A','D','F','P','J'], 
                            'location': ['NY','TX','NY','UT','MA','NV','NY','TX','NY','UT','MA','NV']}, 
                           index = [datetime(2020,5,1,9), datetime(2020,5,1,11), datetime(2020,5,1,12), datetime(2020,5,1,18), datetime(2020,5,2,5), datetime(2020,5,2,10), datetime(2020,5,2,19), datetime(2020,5,3,2), datetime(2020,5,3,10), datetime(2020,5,3,18), datetime(2020,5,4,20), datetime(2020,5,4,22)])

start_time_df = pd.DataFrame({'start_time':[datetime(2020,5,1,8), datetime(2020,5,2,8), datetime(2020,5,3,5)]})
end_time_df = pd.DataFrame({'end_time':[datetime(2020,5,1,17), datetime(2020,5,2,17), datetime(2020,5,3,20)]})

# 1. 合并起止时间,构建工作区间表
work_shifts = pd.DataFrame({
    'start': start_time_df['start_time'],
    'end': end_time_df['end_time']
})

# 2. 创建IntervalIndex,设置closed='both'确保包含区间两端的时间
shift_intervals = pd.IntervalIndex.from_arrays(work_shifts['start'], work_shifts['end'], closed='both')

# 3. 筛选出交易时间落在任意工作区间内的记录
filtered_customer_df = customer_df[customer_df.index.isin(shift_intervals)]
print(filtered_customer_df)

输出结果

customer location
2020-05-01 09:00:00        A       NY
2020-05-01 11:00:00        B       TX
2020-05-01 12:00:00        C       NY
2020-05-02 10:00:00        E       NV
2020-05-03 10:00:00        D       NY
2020-05-03 18:00:00        F       UT

为什么这个方法更好?

  • 性能碾压循环:Pandas的向量化操作是用C实现的,处理十万甚至百万级数据时,速度会比Python循环快几十上百倍
  • 代码更简洁:几行代码就完成了循环的逻辑,可读性更强
  • 扩展性强:如果后续要增加更多工作区间,只需要更新start_time_df和end_time_df即可,无需修改核心逻辑

进阶:关联交易对应的工作时段

如果你还需要知道每条交易属于哪个具体的工作时段,可以用merge_asof来实现,同时保留关联关系:

# 重置索引,把交易时间转为列方便关联
customer_with_time = customer_df.reset_index().rename(columns={'index': 'transaction_time'})
work_shifts_with_id = work_shifts.reset_index().rename(columns={'index': 'shift_id'})

# 用merge_asof匹配最近的不晚于交易时间的工作时段
merged = pd.merge_asof(
    customer_with_time.sort_values('transaction_time'),
    work_shifts_with_id.sort_values('start'),
    left_on='transaction_time',
    right_on='start'
)

# 筛选交易时间不超过对应时段结束时间的记录
final_df = merged[merged['transaction_time'] <= merged['end']].set_index('transaction_time')
print(final_df[['customer', 'location', 'shift_id']])

这个版本会额外输出每条交易对应的工作时段ID,适合需要做更细粒度分析的场景。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.29 04:02:41