
使用 pd.Grouper 进行时间频率分组时,若索引为仅含时间的 datetime.time 或未正确处理时区/日期信息,会导致结果索引被强制归零;正确做法是将时间转为完整 datetime64 类型并配合偏移量校准分组边界。
使用 `pd.grouper` 进行时间频率分组时,若索引为仅含时间的 `datetime.time` 或未正确处理时区/日期信息,会导致结果索引被强制归零;正确做法是将时间转为完整 `datetime64` 类型并配合偏移量校准分组边界。
在 Pandas 中对时间序列数据按固定间隔(如每 10 秒)计算均值时,常误用 pd.Grouper(freq='10S', base=30) 导致输出索引变为 00:00:00 等归零时间——这是因为 pd.Grouper 默认基于 Unix 起始日(1970-01-01)或虚拟日期对齐时间,当输入仅为 HH:MM:SS 字符串且未显式解析为带日期的 datetime64 类型时,Pandas 会补全为 1900-01-01 HH:MM:SS,而分组后又可能因内部标准化逻辑丢失原始日期上下文,最终显示为 00:00:00(即仅保留时间部分的字符串表示)。
根本解决思路:
✅ 将时间列解析为完整 datetime64[ns] 类型(即使无日期,也需确保类型正确);
✅ 不直接依赖 base 参数(其行为在无日期索引下不稳定),改用「手动构造分组键」方式精准控制对齐点;
✅ 通过 pd.to_timedelta 和模运算动态计算每个时间点所属的 10 秒对齐起始时刻,并保留原始时间语义。
以下为推荐实现(支持纯时间显示与完整 datetime 显示两种场景):
import pandas as pd
from io import StringIO
# 示例数据(仅含时间)
data = """Time,Speed
14:01:01,1
14:01:02,1.2
14:01:03,1
14:01:04,1.2
14:01:31,1.3
14:01:33,1.4
14:01:41,1.1
14:01:42,1.2"""
df = pd.read_csv(StringIO(data))
df['Time'] = pd.to_datetime(df['Time'], format='%H:%M:%S') # → datetime64[ns]
df.set_index('Time', inplace=True)
# 关键:手动构造对齐分组键(以每10秒为一组,base=30s 即从 :30 开始对齐)
offset_sec = 30
# 计算当前秒数距离最近向下对齐的 offset 偏移秒数
df['group_key'] = df.index - pd.to_timedelta((df.index.second - offset_sec) % 10, unit='s')
# 分组求均值
result = df.groupby('group_key')['Speed'].mean().reset_index(name='Speed')
# 将 group_key 校正回原始对齐时间点(加上 offset,使区间右闭合)
result['Time'] = result['group_key'] + pd.to_timedelta(offset_sec, unit='s')
result.set_index('Time', inplace=True)
# 【可选】若只需显示 HH:MM:SS(不带日期),取消注释下方两行:
# result.index = result.index.time
# result.index.name = 'Time'
print(result)输出示例:
Speed Time 1900-01-01 14:01:00 1.10 1900-01-01 14:02:00 1.25
✅ 注意事项:
- base 参数在 pd.Grouper 中已逐步被弃用(Pandas ≥ 1.1),官方推荐使用 origin 或手动对齐;本方案兼容所有现代版本;
- 若原始数据不含日期但需长期保留时间语义,建议统一添加一个占位日期(如 1900-01-01),避免 NaT 风险;
- group_key 构造中 (second - offset) % 10 确保每 10 秒一档,+ offset 后得到该组的右边界时间(如 14:01:30–14:01:39 组对应 14:01:40,再减 10 秒得 14:01:30 对齐点);
- 最终 .index.time 可提取纯时间对象,但注意其不可用于后续时间运算(应优先保留 datetime64 类型)。
此方法稳定、透明、可调试,彻底规避 pd.Grouper 在纯时间场景下的索引重置缺陷。

















