Pandas中使用to_datetime避免生成时间戳并按日期区间分组时出现TypeError问题的解决问询
解决日期区间匹配错误并实现无时间戳的时段分组
首先,咱们先揪出报错的直接原因:你在定义掩码的时候,把日期变量date1、date2这些用单引号包起来变成了字符串'date1',而你的question_date是datetime.date类型,字符串和日期类型当然没法用>=、<比较,这就触发了TypeError。
接下来咱们一步步修正并优化你的代码,完全满足你的需求:
第一步:正确处理日期列,彻底去除时间戳
首先要确保日期列是不带时间的纯日期格式,可以这样处理:
import pandas as pd # 初始化你的DataFrame df3 = pd.DataFrame( [['23.02.2012', '23.02.2012', 'aaa'], ['27.02.2014', '27.02.2014', 'bbb'], ['17.08.2018', '17.08.2018', 'ccc'], ['22.07.2019', '22.07.2019', 'ddd']], columns=['date', 'period', 'text'] ) # 把date列转换为datetime类型后,提取纯日期部分(彻底去掉时间戳) df3['date'] = pd.to_datetime(df3['date'], errors='coerce').dt.date # 同步处理question_date列(假设它是从date衍生的) df3['question_date'] = df3['date']
这里用.dt.date把datetime类型转换成纯日期的datetime.date对象,完全消除了时间戳的干扰。
第二步:修正掩码定义,正确使用日期变量
现在定义日期阈值时保持纯日期格式,然后定义掩码时直接用变量名,不要加引号:
# 定义纯日期格式的阈值 date1 = pd.Timestamp('1990-10-14').date() date2 = pd.Timestamp('1994-11-10').date() date3 = pd.Timestamp('1999-10-01').date() date4 = pd.Timestamp('2004-06-13').date() date5 = pd.Timestamp('2009-08-30').date() date6 = pd.Timestamp('2014-10-14').date() date7 = pd.Timestamp('2019-11-26').date() date8 = pd.Timestamp('2021-09-20').date() # 正确定义掩码(注意不要给变量加引号!) mask1 = (df3['question_date'] >= date1) & (df3['question_date'] < date2) mask2 = (df3['question_date'] >= date2) & (df3['question_date'] < date3) mask3 = (df3['question_date'] >= date3) & (df3['question_date'] < date4) mask4 = (df3['question_date'] >= date4) & (df3['question_date'] < date5) mask5 = (df3['question_date'] >= date5) & (df3['question_date'] < date6) mask6 = (df3['question_date'] >= date6) & (df3['question_date'] < date7) mask7 = (df3['question_date'] >= date7) & (df3['question_date'] < date8) # 为匹配的日期区间赋值时段 df3.loc[mask1, 'leg_per'] = '1990-1994' df3.loc[mask2, 'leg_per'] = '1994-1999' df3.loc[mask3, 'leg_per'] = '1999-2004' df3.loc[mask4, 'leg_per'] = '2004-2009' df3.loc[mask5, 'leg_per'] = '2009-2014' df3.loc[mask6, 'leg_per'] = '2014-2019' df3.loc[mask7, 'leg_per'] = '2019-2021'
现在两边都是datetime.date类型,可以正常比较,不会再触发类型错误。
第三步:更高效的替代方案——使用pd.cut
如果你的日期区间是连续且有序的,用pd.cut会比手动写多个掩码更简洁,代码量更少也不容易出错:
# 定义区间边界和对应的时段标签 bins = [date1, date2, date3, date4, date5, date6, date7, date8] labels = ['1990-1994', '1994-1999', '1999-2004', '2004-2009', '2009-2014', '2014-2019', '2019-2021'] # 直接生成leg_per列 df3['leg_per'] = pd.cut( pd.to_datetime(df3['question_date']), # 转换为datetime64类型适配pd.cut bins=pd.to_datetime(bins), labels=labels, include_lowest=True # 包含左边界 )
这里把datetime.date转换回datetime64[ns]类型(pd.to_datetime自动处理),因为pd.cut更适配pandas的datetime类型,最终结果和手动掩码的方式完全一致,但代码更简洁。
验证结果
运行完上面的代码后,你的df3的leg_per列会根据question_date的区间正确赋值:
- 23.02.2012 →
2009-2014 - 27.02.2014 →
2014-2019 - 17.08.2018 →
2014-2019 - 22.07.2019 →
2014-2019
完全符合你的需求,且不会有时间戳的干扰。
内容的提问来源于stack exchange,提问作者id345678
相关产品推荐
相关产品推荐

