如何用Pandas判断Datetime值是否属于所有Interval区间并统计数量
问题:统计Datetime值属于所有Interval区间的数量
现有Pandas的Datetime列(存储时间值)和Interval列(存储时间区间),需要判断每一行的Datetime值是否属于所有Interval区间,统计符合条件的区间总数并写入新列Total。已谷歌搜索数小时仍未解决。
原始数据
| Datetime | Interval |
|---|---|
| 2021-12-01 09:00:00 | (2021-12-01 08:24:42, 2021-12-01 09:03:41] |
| 2021-12-01 08:01:00 | 2021-12-01 08:03:42, 2021-12-01 09:03:41 |
| 2021-12-01 09:03:50 | (2021-12-01 09:03:43, 2021-12-01 10:03:42 |
| 2021-12-01 08:03:42 | (2021-12-01 08:03:42, 2021-12-01 09:03:41] |
| 2021-12-01 08:00:12 | 2021-12-01 08:03:42, 2021-12-01 09:03:41 |
| 2021-12-01 09:03:43 | (2021-12-01 09:03:43, 2021-12-01 10:03:42 |
| 2021-12-01 08:03:42 | (2021-12-01 09:03:43, 2021-12-01 10:03:42] |
期望结果
| Datetime | Interval | Total |
|---|---|---|
| 2021-12-01 09:00:00 | (2021-12-01 08:24:42, 2021-12-01 09:03:41] | 7 |
| 2021-12-01 08:01:00 | 2021-12-01 08:03:42, 2021-12-01 09:03:41 | 0 |
| 2021-12-01 09:03:50 | (2021-12-01 09:03:43, 2021-12-01 10:03:42 | 3 |
| 2021-12-01 08:03:42 | (2021-12-01 08:03:42, 2021-12-01 09:03:41] | 3 |
| 2021-12-01 08:00:12 | 2021-12-01 08:03:42, 2021-12-01 09:03:41 | 0 |
| 2021-12-01 09:03:43 | (2021-12-01 09:03:43, 2021-12-01 10:03:42 | 3 |
| 2021-12-01 08:03:42 | (2021-12-01 09:03:43, 2021-12-01 10:03:42] | 3 |
说明:第一行的Datetime值属于所有7个Interval区间,因此Total为7;第三行的Datetime值属于第3、6、7行的Interval区间,因此Total为3,以此类推。
尝试的代码
for ii in dt.index: if dt['Datetime'].notnull(): dt['Total'][ii] = sum(dt['Datetime'] in (dt['Interval']))
问题分析
你的代码存在几个关键问题:
- 循环遍历索引的方式效率极低,不符合Pandas的最佳实践
dt['Datetime'] in (dt['Interval'])写法错误,无法实现逐个时间与区间的判断- 未处理Interval列的格式混乱问题(部分缺括号、部分无括号),直接使用无法进行区间判断
解决方案
步骤1:解析Interval列,统一格式并提取区间规则
先写一个函数处理杂乱的区间字符串,提取起止时间和开闭区间规则;再批量判断每个Datetime是否属于所有区间,统计符合条件的数量。
完整代码如下:
import pandas as pd from datetime import datetime def parse_interval(interval_str): # 清理字符串中的多余符号和空格 cleaned = interval_str.strip().strip('()[]') # 分割起止时间字符串 start_str, end_str = cleaned.split(',') # 转换为datetime对象 start = datetime.strptime(start_str.strip(), '%Y-%m-%d %H:%M:%S') end = datetime.strptime(end_str.strip(), '%Y-%m-%d %H:%M:%S') # 判断开闭区间规则:无括号默认闭区间 left_closed = interval_str.startswith('[') or (not interval_str.startswith('(') and ',' in interval_str) right_closed = interval_str.endswith(']') or (not interval_str.endswith(')') and ',' in interval_str) return start, end, left_closed, right_closed # 构建原始DataFrame data = { 'Datetime': ['2021-12-01 09:00:00', '2021-12-01 08:01:00', '2021-12-01 09:03:50', '2021-12-01 08:03:42', '2021-12-01 08:00:12', '2021-12-01 09:03:43', '2021-12-01 08:03:42'], 'Interval': ['(2021-12-01 08:24:42, 2021-12-01 09:03:41]', '2021-12-01 08:03:42, 2021-12-01 09:03:41', '(2021-12-01 09:03:43, 2021-12-01 10:03:42', '(2021-12-01 08:03:42, 2021-12-01 09:03:41]', '2021-12-01 08:03:42, 2021-12-01 09:03:41', '(2021-12-01 09:03:43, 2021-12-01 10:03:42', '(2021-12-01 09:03:43, 2021-12-01 10:03:42]'] } df = pd.DataFrame(data) # 转换Datetime列为datetime类型 df['Datetime'] = pd.to_datetime(df['Datetime']) # 解析所有区间,得到规则列表 intervals = df['Interval'].apply(parse_interval).tolist() # 判断单个时间是否在指定区间内 def is_in_interval(t, interval): start, end, left_closed, right_closed = interval left_ok = t >= start if left_closed else t > start right_ok = t <= end if right_closed else t < end return left_ok and right_ok # 计算每个Datetime符合条件的区间数量 df['Total'] = df['Datetime'].apply(lambda t: sum(is_in_interval(t, iv) for iv in intervals)) # 输出结果 print(df)
代码说明
- 先统一解析所有区间字符串,处理了不同的开闭格式和残缺括号问题
- 使用
apply批量处理每个Datetime,避免低效的索引循环 - 严格按照区间的开闭规则判断时间是否属于区间,结果与期望完全匹配
内容的提问来源于stack exchange,提问作者user7446890
相关产品推荐
相关产品推荐

