如何在不将时间设为索引的前提下用pandas between_time()生成时段列
问题描述
有一个包含秒级时间戳的DataFrame,已通过以下代码将时间转换为datetime类型并提取时间部分:
df["start"] = pd.to_datetime(df["start"], unit='s') df["time"] = df["start"].dt.time
需要添加df["timeofday"]列存储时段字符串,对应规则:
- 0:00 - 5:59 → night
- 6:00 - 11:59 → morning
- 12:00 - 17:59 → afternoon
- 18:00 - 21:59 → evening
- 22:00 - 23:59 → night
尝试使用between_time()方法时,因要求索引为DatetimeIndex报错;修改索引后又出现赋值警告或错误,现寻求无需修改原索引的实现方法。
解决方案
方法一:使用pd.cut()按小时快速分段
利用start列的小时属性直接划分时段,无需修改原索引,效率较高:
import pandas as pd # 定义时段区间与对应标签 bins = [-1, 5, 11, 17, 21, 23] labels = ['night', 'morning', 'afternoon', 'evening', 'night'] # 生成timeofday列 df['timeofday'] = pd.cut(df['start'].dt.hour, bins=bins, labels=labels, include_lowest=True)
说明:include_lowest=True确保0点的小时数(0)被包含在第一个区间内,完美匹配时段规则。
方法二:使用np.select()自定义复杂条件
如果需要更灵活的时间判断(比如精确到分钟),可以用np.select()实现:
import numpy as np # 定义各时段的判断条件 conditions = [ (df['start'].dt.hour >= 0) & (df['start'].dt.hour <= 5), (df['start'].dt.hour >= 6) & (df['start'].dt.hour <= 11), (df['start'].dt.hour >= 12) & (df['start'].dt.hour <= 17), (df['start'].dt.hour >= 18) & (df['start'].dt.hour <= 21), (df['start'].dt.hour >= 22) & (df['start'].dt.hour <= 23) ] # 对应条件的结果标签 choices = ['night', 'morning', 'afternoon', 'evening', 'night'] # 生成timeofday列 df['timeofday'] = np.select(conditions, choices, default='night')
说明:如果需要精确到分钟,可把条件改为(df['start'].dt.time >= pd.Timestamp('00:00').time()) & (df['start'].dt.time <= pd.Timestamp('05:59').time())这类形式,同样无需修改索引。
为什么之前的方法失效?
between_time()是Pandas针对DatetimeIndex设计的方法,必须将datetime类型列设为索引才能调用,但修改索引会破坏原DataFrame的结构,还容易引发SettingWithCopyWarning这类赋值警告。上述两种方法直接基于start列的属性进行判断,完全保留原索引结构,避免了这些问题。
内容的提问来源于stack exchange,提问作者Chris
相关产品推荐
相关产品推荐

