如何让Pandas按固定整点/半点分组30分钟时间间隔?
问题:Pandas按固定30分钟间隔(00/30分)统计事件次数时分组偏移的解决方法
我写了一段Pandas代码,想要按每小时00分和30分的固定30分钟间隔统计事件发生次数,但第二组结果始终对齐到03分和33分。怀疑分组是按首行时间对齐,第一组结果正确只是巧合,求问如何让分组器强制对齐到00分和30分?
# load and prepare data df_long_forecast = pd.read_csv('df_long_forecast - reduced.csv') df_long_forecast['after_12_max_datetime'] = pd.to_datetime( df_long_forecast['after_12_max_datetime'] ) df_long_forecast['after_12_max_time'] = ( df_long_forecast['after_12_max_datetime'] - df_long_forecast['after_12_max_datetime'].dt.normalize() ) # timedelta64[ns] # count the number of maxes happening after 12am (absolute and percentage) hist_max = df_long_forecast.groupby( pd.Grouper(key='after_12_max_time', freq='30T', offset='0T', origin='epoch') )['Date'].count() display(hist_max) # count the number of maxes after 12 that result in a profit trade # (cannot be MORE than the previous ones) df_long_forecast_profit = df_long_forecast[ df_long_forecast['after_12_max_>_9_to_12_high'] > 0 ] profit_long = df_long_forecast_profit.groupby( pd.Grouper(key='after_12_max_time', freq='30T', offset='0T', origin='epoch') )['Date'].count() display(profit_long)
hist_max输出:
after_12_max_time 0 days 12:00:00 24 0 days 12:30:00 5 0 days 13:00:00 7 0 days 13:30:00 5 0 days 14:00:00 5 0 days 14:30:00 4 0 days 15:00:00 4 0 days 15:30:00 1 0 days 16:00:00 5 0 days 16:30:00 7 0 days 17:00:00 1 0 days 17:30:00 6 0 days 18:00:00 1 0 days 18:30:00 1 0 days 19:00:00 1 0 days 19:30:00 6 0 days 20:00:00 3 0 days 20:30:00 0 0 days 21:00:00 6 0 days 21:30:00 19 0 days 22:00:00 8 Freq: 30T, Name: Date, dtype: int64
profit_long输出:
after_12_max_time 0 days 12:03:00 8 0 days 12:33:00 4 0 days 13:03:00 5 0 days 13:33:00 4 0 days 14:03:00 5 0 days 14:33:00 4 0 days 15:03:00 3 0 days 15:33:00 2 0 days 16:03:00 5 0 days 16:33:00 6 0 days 17:03:00 2 0 days 17:33:00 5 0 days 18:03:00 1 0 days 18:33:00 2 0 days 19:03:00 0 0 days 19:33:00 5 0 days 20:03:00 3 0 days 20:33:00 0 0 days 21:03:00 6 0 days 21:33:00 21 0 days 22:03:00 3 Freq: 30T, Name: Date, dtype: int64
问题原因
问题出在你使用origin='epoch'且分组对象是timedelta类型数据。对timedelta使用pd.Grouper时,origin='epoch'会让分组从1970-01-01 00:00:00对应的timedelta起点开始,过滤后的子数据集(比如df_long_forecast_profit)的首个时间会触发分组偏移,导致间隔错位。
解决方法
方法1:直接基于datetime列分组(推荐)
利用datetime的分组逻辑,配合origin='start_day'强制以当天00:00为起点对齐30分钟间隔,最后可保留时间部分匹配原输出格式:
# 统计所有事件 hist_max = df_long_forecast.groupby( pd.Grouper(key='after_12_max_datetime', freq='30T', origin='start_day') )['Date'].count() # 仅保留时间部分作为索引(可选) hist_max.index = hist_max.index.time display(hist_max) # 统计盈利事件 df_long_forecast_profit = df_long_forecast[df_long_forecast['after_12_max_>_9_to_12_high'] > 0] profit_long = df_long_forecast_profit.groupby( pd.Grouper(key='after_12_max_datetime', freq='30T', origin='start_day') )['Date'].count() profit_long.index = profit_long.index.time display(profit_long)
方法2:手动对齐timedelta
如果必须使用timedelta列,可通过秒数计算手动对齐到30分钟间隔:
def align_30min(td): total_seconds = td.total_seconds() # 1800秒=30分钟,取整后转回timedelta aligned_seconds = round(total_seconds / 1800) * 1800 return pd.to_timedelta(aligned_seconds, unit='s') # 应用对齐函数到全量数据 df_long_forecast['aligned_time'] = df_long_forecast['after_12_max_time'].apply(align_30min) hist_max = df_long_forecast.groupby('aligned_time')['Date'].count() display(hist_max) # 应用到盈利数据 df_long_forecast_profit['aligned_time'] = df_long_forecast_profit['after_12_max_time'].apply(align_30min) profit_long = df_long_forecast_profit.groupby('aligned_time')['Date'].count() display(profit_long)
关键说明
origin='start_day'会让分组从当天00:00开始,确保30分钟间隔严格对齐到00分和30分,不受数据中最早时间的影响。- 直接使用datetime列分组比timedelta更可靠,Pandas对datetime的分组逻辑更成熟,能更好地处理固定间隔对齐。
内容的提问来源于stack exchange,提问作者fede72bari
相关产品推荐
相关产品推荐

