-
-
Notifications
You must be signed in to change notification settings - Fork 18.5k
QST: Howto write a custom DateOffset #35569
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
Instead of subclasses DateOffset, can you try subclassing pd._libs.tslibs.offsets.BaseOffset? You'll probably want to get apply_wraps from tslibs.offsets too |
Great, this does the trick! Thanks. Question: Was the offset API always considered private? Are we doing something uncommon by writing our own offsets? I never found our code pretty, nor elegant, but our offsets were doing what we needed for the past years. Is there a more common way to implement things? |
Its not unheard of, but not super-common. In some cases people upstream the functionality into pandas' built-in offsets.
Not really. We semi-recently moved the implementation into cython for performance reasons, evidently made subclassing more difficult. If you'd like to make a PR documenting how to subclass, that would be welcome. Be sure to alias |
Thanks, that one problem is gone 👍 Another thing broken for me now is a YearOffset, that starts at a specific date. Here is the code: def year_with_date_offset(day, month):
"""Creates and instantiates an offset class incrementing yearly always starting
at a specified day and month.
The class is created on the fly as the original Pandas classes do not allow to
parametrize the start day."""
class YearWithDate(pd._libs.tslibs.offsets.YearOffset): # noqa
_default_month = month
_day_opt = day
_prefix = "ASD"
@property
def rule_code(self):
return "{parent}-{day}".format(parent=super().rule_code, day=self._day_opt)
return YearWithDate() Any hint to archive this now? |
Does |
>>> import pandas as pd
>>> o = pd._libs.tslibs.offsets.DateOffset(years=1, month=3, day=5)
>>> pd.date_range(start="2017", periods=3, freq=o)
DatetimeIndex(['2017-01-01', '2018-03-05', '2019-03-05'], dtype='datetime64[ns]', freq='<DateOffset: day=5, month=3, years=1>') Kinda, as the first one, only defined via year, will not be on that specific date. |
That looks like a problem in |
Not sure if this is the real problem. Tried it with this: def is_on_offset(self, dt: datetime) -> bool:
if self.normalize and not _is_normalized(dt): # noqa
return False
elif self.day == dt.day and self.month == dt.month:
return True
return False which results in: o.is_on_offset(pd.Timestamp("2017-01-01")) # False
o.is_on_offset(pd.Timestamp("2017-05-03")) # True Now the date is correct, but the year is one too far in the future. r = pd.date_range(start="2017", periods=5, freq=o) # DatetimeIndex(['2018-05-03', '2019-05-03', '2020-05-03', '2021-05-03', '2022-05-03'], dtype='datetime64[ns]', freq='ASD-5-3') |
@jbrockmendel Are you suggesting to change/add Something like
|
I think RelativeDeltaOffset.is_on_offset should look like:
When I do this, I get:
which looks right to me. |
I fear not, the first index should be |
After all its is about As I am running out of time and the offset is not that performance critical for now, I created a quick hack for my needs:
|
Glad to hear you've got a working fix. Hopefully we can still find a longer-term solution to implement within pandas.
Given the existing semantics of RelativeDeltaOffset (RDO), I think it should be 2018-03-05. Internally, the RDO doesn't look at the years/month/day attributes, just the |
I found this question while I was looking after a similar problem - I need a frequency for three periods dividing a month (known as decade but for days not years): Days: 1-10, 11-20 and 20-28/29/30/31. These decades are common in agro-metereology. Is there any documentation other than this question to guide me? What is the |
Any update on this? |
We need multiple custom DateOffset, e.g. so called
MonthHalf
.Until Release 1.1.0 we had a working solution:
With release 1.1.0 (and i guess the merge of #34062) code is broken.
E.g. The rollback is not working anymore:
How can i implement such need now?
The text was updated successfully, but these errors were encountered: