Pandas通过添加分数时间增量消除重复DateTime索引实现索引单调递增
重复DateTime索引分数秒去重实现方案
核心实现逻辑是按“单组重复时间跨度1秒,按组内行序等分增量”的规则,直接在全表范围计算时间增量,无需单独筛选重复行做二次切片,最终可保证索引严格单调递增。
实现步骤
- 基于原始DateTime索引分组,统计每一行在同时间戳组内的行序号(从0开始计数)
- 统计每个时间戳对应的总重复行数
- 按照
(行序 / 组总重复行数)计算每一行需要叠加的秒级增量 - 将增量叠加到原始索引上,生成新的无重复时间戳索引
可直接运行的实现代码
import pandas as pd import numpy as np import datetime as dt # 复现测试用带重复索引的DataFrame n = 8 np.random.seed(42) df = pd.DataFrame(index=[dt.datetime(2020,3,31,9,25) + dt.timedelta(seconds=x) for x in np.random.randint(0,10000,size=n).tolist()], data=np.random.randint(0,100,size=(n, 2)), columns=['price', 'volume']).sort_index() df.index.name = 'timestamp' df = df.append(df.iloc[[3,6]]+1) df = df.append(df.iloc[3]+1) df = df.append(df.iloc[3]).sort_index() # 核心增量计算 # 同时间戳组内的行序号 group_order = df.index.to_series().groupby(df.index).cumcount() # 同时间戳组的总行数 group_total = df.index.to_series().groupby(df.index).transform("count") # 计算等距时间增量,单位为秒 time_increment = pd.to_timedelta(group_order / group_total, unit="s") # 更新索引 df.index = df.index + time_increment
效果说明
- 非重复时间戳的行,组内序号为0、组总行数为1,计算得到的增量为0,完全保留原始时间精度
- 针对
11:09:25的2行重复组,对应增量为0s、0.5s,最终生成的索引为2020-03-31 11:09:25.000、2020-03-31 11:09:25.500,和给出的预期输出完全匹配 - 针对
10:51:31的4行重复组,对应增量为0s、0.25s、0.5s、0.75s,最终生成的索引严格在原时间戳基础上按等距微秒级递增,不存在索引倒序的问题。给出的预期输出中该组第四行标注为10:51:31.000属于笔误,按等分增量规则计算该行应叠加0.5s增量,不会出现时间戳回退的情况。 - 全流程采用向量化计算,在万行甚至百万行规模的数据集上,运行效率远高于逐重复组切片修改索引的实现方式。
内容的提问来源于stack exchange,提问作者steff
相关产品推荐
相关产品推荐

