熊猫 :更有效地将日期偏移量添加到日期矢量



我有一个带有时间戳(ind(的熊猫索引和一个带有整数的numpy数组(off(,这些整数表示我想添加indIndex的日历天数。

例如:

import pandas
ind =  pd.date_range("2019-1-1T12:00", "2019-12-31T12:00", freq="D", tz="Europe/Paris")
off = pd.np.ones(len(i))

我想得到第一个向量的日期(不是日期时间(加上第二个向量的天数之和。

这是一个代码,它给了我想要的东西:

def f(ind, off):
o = pd.Index( i.floor("D") + pd.DateOffset(days=o) for i,o in zip(ind, off) )
return o
o = f(ind, off)

但它非常慢(时间的结果是"o = f(ind, off("(:

126 ms ± 4.47 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)

我想这是因为我使用 python 列表理解而不是来自 numpy 或 pandas 的 C 函数。

考虑到这一点,这是我编写的几乎可以工作的代码:

def g(ind, off):
o = ind.floor("D") + pd.to_timedelta(off, unit="days")
return o
o = g(ind, off)

它要快得多:

1.28 ms ± 247 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

但它也是错误的,因为它添加了 24 小时时间增量而不是日历日,这不是我想要的,因为我在欧洲/巴黎时区:

print( f(ind, off).hour.unique())
print( g(ind, off).hour.unique())

给我 :

Int64Index([0], dtype='int64')
Int64Index([0, 1, 23], dtype='int64')

我希望有一个与第二个解决方案一样快的解决方案,但给出像第一个一样的正确答案。知道吗?

欢迎来到夏令时的疯狂世界。如果您只是在fg之间进行快速比较,它们每天都匹配,除了时钟变化的日子:

f = pd.Index([i.floor("D") + pd.DateOffset(days=o) for i,o in zip(ind, off)])
g1 = ind.floor('D') + pd.to_timedelta(off, unit="days")
# Show when f != g1
pd.DataFrame({'f': f, 'g1': g1}).query('f != g1')
f                        g1
89  2019-04-01 00:00:00+02:00 2019-04-01 01:00:00+02:00
299 2019-10-28 00:00:00+01:00 2019-10-27 23:00:00+01:00

这是为什么呢?3月31日和10月27日是欧盟2019年的两个时钟变化日。在 3 月 31 日,时钟提前 1 小时,因此 24 小时的时间增量变为 25。相反,在 10 月 27 日,时钟追溯到 1 小时,因此 24 变为 23。熊猫试图为你适应时钟的变化,但碰巧这不是你想要的。

我能想到的几个选项...

首先,将所有日期转换为单个时区(如巴黎(,然后删除时区信息并带有tz_localize(None)

g2 = ind.tz_localize(None).floor('D') + pd.to_timedelta(off, unit='days')
pd.DataFrame({'f': f.tz_localize(None), 'g2': g2}).query('f != g2')         # empty frame

二:添加时间增量后执行floor操作:

g3 = (ind + pd.to_timedelta(off, unit='days')).floor('D')
pd.DataFrame({'f': f, 'g3': g3}).query('f != g3')       # empty again

最新更新