如何基于Pandas Timedelta多条件生成time_of_day列?
解决DataFrame新增时段列的错误与优化方案
错误根源
你碰到的ValueError,核心问题是conditions函数里误用了整个df['TIME']列来做判断——当用apply(axis=1)逐行处理时,函数参数s代表单行数据,你应该基于当前行的s['TIME']来判断,而非整个列的Series(Series包含多个布尔值,Python无法确定其整体的真假,所以报错)。另外最后一个Night的条件逻辑完全错误:时间不可能同时满足>=23:00且<06:00,应该直接用else兜底或者拆成两个条件的或逻辑。
快速修复:修正apply函数
把函数里的df['TIME']替换为当前行的s['TIME'],同时简化条件逻辑:
def conditions(s): time = pd.to_timedelta(s['TIME']) if '06:00:00' <= time < '13:00:00': return "Morning" elif '13:00:00' <= time < '18:00:00': return "Afternoon" elif '18:00:00' <= time < '23:00:00': return "Evening" else: return "Night" df['TIME_OF_DAY'] = df.apply(conditions, axis=1)
这样每个判断都是基于当前行的单个时间值,不会再出现布尔歧义问题。
更高效的向量化方案(推荐)
apply逐行处理效率极低,数据量一大就会卡,推荐用向量化方法实现:
方案1:np.select批量判断
import numpy as np # 先把TIME转为timedelta类型(一次性转换比逐行转高效) df['time_delta'] = pd.to_timedelta(df['TIME']) # 定义批量判断的条件和对应结果 cond_list = [ (df['time_delta'] >= '06:00:00') & (df['time_delta'] < '13:00:00'), (df['time_delta'] >= '13:00:00') & (df['time_delta'] < '18:00:00'), (df['time_delta'] >= '18:00:00') & (df['time_delta'] < '23:00:00') ] result_list = ['Morning', 'Afternoon', 'Evening'] # 批量赋值,不满足任何条件的默认设为Night df['TIME_OF_DAY'] = np.select(cond_list, result_list, default='Night') # 清理临时列 df.drop('time_delta', axis=1, inplace=True)
方案2:pd.cut按区间划分
先提取小时数,再用区间快速分组:
# 把TIME转为时间格式,提取小时数 df['hour'] = pd.to_datetime(df['TIME'], format='%H:%M').dt.hour # 定义区间边界和对应标签 bins = [-1, 6, 13, 18, 23, 24] labels = ['Night', 'Morning', 'Afternoon', 'Evening', 'Night'] # 按区间给每个小时分配时段标签 df['TIME_OF_DAY'] = pd.cut(df['hour'], bins=bins, labels=labels, include_lowest=True) # 清理临时列 df.drop('hour', axis=1, inplace=True)
这两种方法都是批量处理,执行速度比apply快几十甚至上百倍,适合大规模数据。
内容的提问来源于stack exchange,提问作者dspractician
相关产品推荐
相关产品推荐

