【发布时间】:2017-04-08 16:54:40
【问题描述】:
我正在处理不定期记录的财务数据。一些时间戳是重复的,这使得分析变得棘手。这是一个数据示例 - 注意有四个 2016-08-23 00:00:17.664193 时间戳:
In [167]: ts
Out[168]:
last last_sz bid ask
datetime
2016-08-23 00:00:14.161128 2170.75 1 2170.75 2171.00
2016-08-23 00:00:14.901180 2171.00 1 2170.75 2171.00
2016-08-23 00:00:17.196639 2170.75 1 2170.75 2171.00
2016-08-23 00:00:17.664193 2171.00 1 2170.75 2171.00
2016-08-23 00:00:17.664193 2171.00 1 2170.75 2171.00
2016-08-23 00:00:17.664193 2171.00 2 2170.75 2171.00
2016-08-23 00:00:17.664193 2171.00 1 2170.75 2171.00
2016-08-23 00:00:26.206108 2170.75 2 2170.75 2171.00
2016-08-23 00:00:28.322456 2170.75 7 2170.75 2171.00
2016-08-23 00:00:28.322456 2170.75 1 2170.75 2171.00
在这个例子中,只有少数重复,但在某些情况下,有数百个连续的行,都共享相同的时间戳。我的目标是通过为每个重复添加 1 个额外的纳秒来解决这个问题(因此,在 4 个连续相同时间戳的情况下,我会在第二个时间戳中添加 1ns,在第三个中添加 2ns,在第四个中添加 3ns。例如,上面的数据将被转换为:
In [169]: make_timestamps_unique(ts)
Out[170]:
last last_sz bid ask
newindex
2016-08-23 00:00:14.161128000 2170.75 1 2170.75 2171.0
2016-08-23 00:00:14.901180000 2171.00 1 2170.75 2171.0
2016-08-23 00:00:17.196639000 2170.75 1 2170.75 2171.0
2016-08-23 00:00:17.664193000 2171.00 1 2170.75 2171.0
2016-08-23 00:00:17.664193001 2171.00 1 2170.75 2171.0
2016-08-23 00:00:17.664193002 2171.00 2 2170.75 2171.0
2016-08-23 00:00:17.664193003 2171.00 1 2170.75 2171.0
2016-08-23 00:00:26.206108000 2170.75 2 2170.75 2171.0
2016-08-23 00:00:28.322456000 2170.75 7 2170.75 2171.0
2016-08-23 00:00:28.322456001 2170.75 1 2170.75 2171.0
我一直在努力寻找一个好的方法来做到这一点 - 我目前的解决方案是进行多次传递,每次检查重复项,并将 1ns 添加到除了一系列相同时间戳中的第一个之外的所有时间戳。代码如下:
def make_timestamps_unique(ts):
mask = ts.index.duplicated('first')
duplicate_count = np.sum(mask)
passes = 0
while duplicate_count > 0:
ts.loc[:, 'newindex'] = ts.index
ts.loc[mask, 'newindex'] += pd.Timedelta('1ns')
ts = ts.set_index('newindex')
mask = ts.index.duplicated('first')
duplicate_count = np.sum(mask)
passes += 1
print('%d passes of duplication loop' % passes)
return ts
这显然是非常低效的 - 它通常需要数百次通过,如果我在 200 万行数据帧上尝试它,我会得到 MemoryError。有什么更好的方法来实现这一点吗?
【问题讨论】: