【发布时间】:2021-03-20 12:35:21
【问题描述】:
给定一个锚定日期和一个日期偏移量,我如何将偏移量回滚到给定目标日期之前的第一个有效日期?
anchor = pd.to_datetime("2021-03-19")
target = pd.to_datetime("2021-03-04")
offset = pd.DateOffset(weeks=2)
# something like this... resulting in "2021-02-19"
first_before = offset.rollback(anchor, target)
# Want to point out that rollback is functional with most other offsets, such
# as pd.offsets.Week(...).rollback(...). However, rolling back a DateOffset
# returns the same input date (because there is no anchor).
将DateOffset 转换为Timedelta 并自行计算。下面进行了简化,以忽略锚定日期出现在目标日期之前的可能性。
first_before = anchor - math.ceil((anchor-target)/pd.Timedelta(weeks=2)) * offset
但Timedelta 不会忽略夏令时,因此结果可能会关闭 +- 1 小时。另外DateOffset是唯一一个不能直接转换成Timedelta的偏移量,有各种等效规格,手动转换有点麻烦。
o1 = pd.offsets.DateOffset(weeks=2)
o2 = pd.offsets.DateOffset(days=14)
# Both raise ValueError:
pd.Timedelta(o1)
pd.to_timedelta(o1)
# Both raise AtttributeError:
o1.days
o2.weeks
但最后我觉得肯定有一种我不知道的更简单的内置方法。
edit:展示一种低效的方法。
给定以下日期范围,我想找到小于或等于“2021-03-04”的第一个日期(目标)。
# end is anchor, freq is offset
>>> dr = pd.date_range(freq=offset, end="2021-03-19", periods=20)
>>> dr
DatetimeIndex(['2020-06-26', '2020-07-10', '2020-07-24', '2020-08-07',
'2020-08-21', '2020-09-04', '2020-09-18', '2020-10-02',
'2020-10-16', '2020-10-30', '2020-11-13', '2020-11-27',
'2020-12-11', '2020-12-25', '2021-01-08', '2021-01-22',
'2021-02-05', '2021-02-19', '2021-03-05', '2021-03-19'],
dtype='datetime64[ns]', freq='<DateOffset: weeks=2>')
# key is target
>>> dr[dr.get_loc(key="2021-03-04", method="ffill")]
Timestamp('2021-02-19 00:00:00', freq='<DateOffset: weeks=2>')
【问题讨论】:
-
如果你的锚是
2021-03-19,目标日期为2021-03-04,偏移量为2 weeks,为什么预期的答案是2021-02-19而不是2021-02-18或2021-02-25?你能重新解释一下锚点和目标是如何工作的吗? -
@user19087 据我所知,pandas 中没有任何内置函数可以为您回滚,但我想这可以通过简单的 for/while 循环并结合回滚来简单地实现里面的逻辑..
-
如果没有内置函数,我希望直接计算忽略夏令时(即不改变时间)而不是循环(时间效率低)或日期时间索引(空间效率低)。