-
- Notifications
You must be signed in to change notification settings - Fork 19.3k
REF: Make PeriodArray an ExtensionArray #22862
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
Changes from 1 commit
eaadcbc a05928a 3c0d9ee 63fc3fa 7d5d71c e5caac6 c194407 eb4506b 1b9fd7a 0fa0ed1 3247ea8 c162cdd 611d378 fb2ff82 25a380f 1b2c4ec d04293e eacad39 70cd3b8 9b22889 87d289a 6369c7f 01551f0 0437940 42ab137 298390f 23e5cfc 9d17fd2 959cd72 b66f617 5669675 2c0311c 012be1c c3a96d0 67faabc ff7c06c c2d57bd fbde770 1c4bbe7 b395c90 d68a5c5 0c7b704 d26d3d2 e4babea 7f6c144 b4aa4ca 6a70131 9aa077c 411738c 8e0fb69 6d98e85 6d9e150 4899479 634def1 1f18452 2f92b22 23f232c dd3b8cd 1a7c360 87ecb64 0bde329 2d85a82 438e6b5 a9456fd ac05365 36ed547 4652ca7 a047a1b a4a30d7 1441ae6 8003808 5f43753 1c13d0f bae6b3d f422cf0 0229d74 aa40cf4 29085e1 00ffddf e81fa9c 0c8925f 96204a1 82930f7 8d24582 1fc7744 6cd428c 21693e0 b65ffad 1f438e3 f3928fb 089f8ab 700650a 452c229 e3e0e57 78751c2 203d561 eb1c67d e08aa79 c1ee04b 827e563 ca4a7fd ed185c0 b3407ac a4011eb fc1ca3c 1b1841f b3b315a 3ab4176 8102475 8c329eb 78d4960 4e3d914 5e4aaa7 7f77563 f88d6f7 7aa78ba 2d737f8 833899a 236b49c 8230347 bf33a57 738acfe 032ec02 77e389a 61031d7 a094b3d ace4856 fc6a1c7 900afcf 0baa3e9 f95106e e57e24a ce1c970 a7e1216 2548d6a 02e3863 1997cff af2d1de 64f5778 4151510 ac9bd41 5462bd7 c1c6428 7ab2736 bd6f966 8068daf 5691506 575d61a 4065bdb File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
- Loading branch information
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| | @@ -113,9 +113,32 @@ class PeriodArray(DatetimeLikeArrayMixin, ExtensionArray): | |
| """ | ||
| _attributes = ["freq"] | ||
| _typ = "period" # ABCPeriodArray | ||
| | ||
| # Names others delegate to us on | ||
| _other_ops = [] | ||
| _bool_ops = ['is_leap_year'] | ||
| _object_ops = ['start_time', 'end_time', 'freq'] | ||
| _field_ops = ['year', 'month', 'day', 'hour', 'minute', 'second', | ||
| 'weekofyear', 'weekday', 'week', 'dayofweek', | ||
| 'dayofyear', 'quarter', 'qyear', | ||
| 'days_in_month', 'daysinmonth'] | ||
| _datetimelike_ops = _field_ops + _object_ops + _bool_ops | ||
| _datetimelike_methods = ['strftime', 'to_timestamp', 'asfreq'] | ||
| | ||
| # -------------------------------------------------------------------- | ||
| # Constructors | ||
| | ||
| @property | ||
| def _foo(self): | ||
| return 'foo!' | ||
| | ||
| @_foo.setter | ||
| def _foo(self, value): | ||
| print("setting foo to ", value) | ||
| | ||
| def _bar(self, arg, kwarg=1): | ||
| print(arg, kwarg) | ||
| | ||
| def __new__(cls, data=None, ordinal=None, freq=None, start=None, end=None, | ||
| periods=None, tz=None, dtype=None, copy=False, | ||
| ||
| **fields): | ||
| | @@ -511,11 +534,27 @@ def shift(self, periods=1): | |
| ------- | ||
| shifted : Period Array/Index | ||
| """ | ||
| # We have two kinds of shift. | ||
| ||
| # 1. ExtensionArray.shift: move positions of each value, | ||
| # fill NA on the end | ||
| # 2. Datelike.tshift: move each value through time | ||
| # Each Datelike array will implement both. It's up to the | ||
| # caller to call the correct one. | ||
| return self._ea_shift(periods=periods) | ||
| | ||
| def _ea_shift(self, periods=1): | ||
| # TODO: remove from DatetimeLikeArrayMixin | ||
| # The semantics for Index.shift differ from EA.shift | ||
| # then just call super. | ||
| return ExtensionArray.shift(self, periods) | ||
| | ||
| def _tshift(self, n, freq=None): | ||
| # TODO: docs | ||
| values = self.values + n * self.freq.n | ||
| if self.hasnans: | ||
| values[self._isnan] = iNaT | ||
| return self._simple_new(values, freq=self.freq) | ||
| | ||
| def _maybe_convert_timedelta(self, other): | ||
| """ | ||
| Convert timedelta-like input to an integer multiple of self.freq | ||
| | @@ -628,7 +667,8 @@ def end_time(self): | |
| | ||
| PeriodArray._add_comparison_ops() | ||
| PeriodArray._add_datetimelike_methods() | ||
| | ||
| # PeriodArray._add_numeric_methods_disabled() | ||
| # PeriodArray._add_logical_methods_disabled() | ||
| | ||
| # ------------------------------------------------------------------- | ||
| # Constructor Helpers | ||
| | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,6 +1,7 @@ | ||
| # pylint: disable=E1101,E1103,W0232 | ||
| from datetime import datetime | ||
| import numpy as np | ||
| import operator | ||
| import warnings | ||
| | ||
| from pandas.core import common as com | ||
| | @@ -20,6 +21,7 @@ | |
| import pandas.tseries.frequencies as frequencies | ||
| from pandas.tseries.frequencies import get_freq_code as _gfc | ||
| | ||
| from pandas.core.accessor import PandasDelegate, delegate_names | ||
| from pandas.core.indexes.datetimes import DatetimeIndex, Int64Index, Index | ||
| from pandas.core.indexes.datetimelike import DatelikeOps, DatetimeIndexOpsMixin | ||
| from pandas.core.tools.datetimes import parse_time_string | ||
| | @@ -64,8 +66,23 @@ def _new_PeriodIndex(cls, **d): | |
| return cls._from_ordinals(values=values, **d) | ||
| | ||
| | ||
| class PeriodDelegateMixin(PandasDelegate): | ||
| """ | ||
| Delegate from PeriodIndex to PeriodArray. | ||
| """ | ||
| def _delegate_property_get(self, name, *args, **kwargs): | ||
| return getattr(self._data, name) | ||
| | ||
| def _delegate_property_set(self, name, value, *args, **kwargs): | ||
| setattr(self._data, name, value) | ||
| | ||
| def _delegate_method(self, name, *args, **kwargs): | ||
| return operator.methodcaller(name, *args, **kwargs)(self._data) | ||
| | ||
| | ||
| # @delegate_names(PeriodArray, PeriodArray._datetimelike_methods, typ="method") | ||
| class PeriodIndex(DatelikeOps, DatetimeIndexOpsMixin, | ||
| Int64Index): | ||
| Int64Index, PeriodDelegateMixin): | ||
| Contributor Author There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Are people OK with PeriodIndex also being an accessor? That seemed like the easiest way to dispatch things down to PeriodArray. Member There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is performance affected? I'm still in the "inheritance is the easiest way to dispatch" camp, but recognize that I've lost this one. Contributor Author There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Beyond an extra function call (or two), I don't think so, though I will check. These aren't descriptors so we aren't changing getattribute. Contributor There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. we could make a generic mechanism to do this at some point. We are eventually going to be doing this with all Index. Member There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Related to that, as I think this is for a follow-up, how do we keep track of the follow-up ideas? Update a list in the top-post (to not have it somewhere in the middle be hidden by github) | ||
| """ | ||
| Immutable ndarray holding ordinal values indicating regular periods in | ||
| time such as particular years, quarters, months, etc. | ||
| | @@ -145,19 +162,9 @@ class PeriodIndex(DatelikeOps, DatetimeIndexOpsMixin, | |
| """ | ||
| _typ = 'periodindex' | ||
| _attributes = ['name', 'freq'] | ||
| _delegated_to = PeriodArray | ||
| # _delegated_to = PeriodArray | ||
| | ||
| # define my properties & methods for delegation | ||
| _other_ops = [] | ||
| _bool_ops = ['is_leap_year'] | ||
| _object_ops = ['start_time', 'end_time', 'freq'] | ||
| _field_ops = ['year', 'month', 'day', 'hour', 'minute', 'second', | ||
| 'weekofyear', 'weekday', 'week', 'dayofweek', | ||
| 'dayofyear', 'quarter', 'qyear', | ||
| 'days_in_month', 'daysinmonth'] | ||
| _datetimelike_ops = _field_ops + _object_ops + _bool_ops | ||
| _datetimelike_methods = ['strftime', 'to_timestamp', 'asfreq'] | ||
| | ||
| _is_numeric_dtype = False | ||
| _infer_as_myclass = True | ||
| | ||
| | @@ -339,13 +346,8 @@ def shift(self, n): | |
| ------- | ||
| shifted : PeriodIndex | ||
| """ | ||
| # TODO: docs | ||
| # Note, this differs from the definition of ExtensionArray.shift | ||
| # so we don't dispatch | ||
| values = self._ndarray_values + n * self.freq.n | ||
| if self.hasnans: | ||
| values[self._isnan] = tslib.iNaT | ||
| return self._shallow_copy(values=values) | ||
| i8values = self._data._tshift(n) | ||
| return self._simple_new(i8values, name=self.name, freq=self.freq) | ||
| | ||
| def _coerce_scalar_to_index(self, item): | ||
| """ | ||
| | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These go, right?