gpt4 book ai didi

python - 修改 Pandas 中的时间戳以使索引唯一

转载 作者:太空狗 更新时间:2023-10-29 22:12:31 24 4
gpt4 key购买 nike

我正在处理不定期记录的财务数据。一些时间戳是重复的,这使得分析变得棘手。这是数据示例 - 注意有四个 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。对于实现此目标的更好方法有什么想法吗?

最佳答案

这是一个更快的 numpy 版本(但可读性稍差),它的灵感来自于这个 SO article 。这个想法是在重复的时间戳值上使用 cumsum,同时在每次遇到 np.NaN 时重置累积和:

# get duplicated values as float and replace 0 with NaN
values = df.index.duplicated(keep=False).astype(float)
values[values==0] = np.NaN

missings = np.isnan(values)
cumsum = np.cumsum(~missings)
diff = np.diff(np.concatenate(([0.], cumsum[missings])))
values[missings] = -diff

# print result
result = df.index + np.cumsum(values).astype(np.timedelta64)
print(result)

DatetimeIndex([ '2016-08-23 00:00:14.161128',
'2016-08-23 00:00:14.901180',
'2016-08-23 00:00:17.196639',
'2016-08-23 00:00:17.664193001',
'2016-08-23 00:00:17.664193002',
'2016-08-23 00:00:17.664193003',
'2016-08-23 00:00:17.664193004',
'2016-08-23 00:00:26.206108',
'2016-08-23 00:00:28.322456001',
'2016-08-23 00:00:28.322456002'],
dtype='datetime64[ns]', name='datetime', freq=None)

计时此解决方案会产生 10000 loops, best of 3: 107 µs per loop 而 @DYZ groupby/apply 方法(但更具可读性)在使用 100 loops, best of 3: 5.3 ms per loop 的虚拟数据上大约慢 50 倍。

当然,最后还得重新设置索引:

df.index = result

关于python - 修改 Pandas 中的时间戳以使索引唯一,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43297853/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com