From bda766eb142324acc2c866a9593167b1b31c9984 Mon Sep 17 00:00:00 2001 From: Brock Mendel Date: Wed, 22 Nov 2017 08:33:18 -0800 Subject: [PATCH] implement .dt accessor for Index classes --- doc/source/whatsnew/v0.22.0.txt | 2 +- pandas/core/indexes/base.py | 15 +++++++++++++++ pandas/core/indexes/datetimelike.py | 5 +++++ pandas/tests/indexes/common.py | 9 +++++++++ 4 files changed, 30 insertions(+), 1 deletion(-) diff --git a/doc/source/whatsnew/v0.22.0.txt b/doc/source/whatsnew/v0.22.0.txt index b845e84d433f7..882384d1d0f7a 100644 --- a/doc/source/whatsnew/v0.22.0.txt +++ b/doc/source/whatsnew/v0.22.0.txt @@ -59,7 +59,7 @@ Other API Changes - `tseries.frequencies.get_freq_group()` and `tseries.frequencies.DAYS` are removed from the public API (:issue:`18034`) - :func:`Series.truncate` and :func:`DataFrame.truncate` will raise a ``ValueError`` if the index is not sorted instead of an unhelpful ``KeyError`` (:issue:`17935`) - :func:`Dataframe.unstack` will now default to filling with ``np.nan`` for ``object`` columns. (:issue:`12815`) - +- :class:`Index` now has a `.dt` property that behaves like `Series.dt` (:issue:`17134`) .. _whatsnew_0220.deprecations: diff --git a/pandas/core/indexes/base.py b/pandas/core/indexes/base.py index 7a34e64724245..804f796eb8a1d 100644 --- a/pandas/core/indexes/base.py +++ b/pandas/core/indexes/base.py @@ -1641,6 +1641,21 @@ def is_all_dates(self): return False return is_datetime_array(_ensure_object(self.values)) + @property + def dt(self): + """ + For a datetime-like Index object, `self.dt` returns `self` so that + datetime-like attributes can be accessed symmetrically for Index + and Series objects. + + For Index objects that are not datetime-like, `self.dt` will raise + an AttributeError. + """ + # Non-raising versions of the `.dt` attribute are available in + # DatetimeIndex, PeriodIndex, and TimedeltaIndex. + raise AttributeError("Can only use .dt accessor with datetimelike " + "values") + def __reduce__(self): d = dict(data=self._data) d.update(self._get_attributes_dict()) diff --git a/pandas/core/indexes/datetimelike.py b/pandas/core/indexes/datetimelike.py index 4934ccb49b844..73eaa5ff74552 100644 --- a/pandas/core/indexes/datetimelike.py +++ b/pandas/core/indexes/datetimelike.py @@ -124,6 +124,11 @@ def ceil(self, freq): class DatetimeIndexOpsMixin(object): """ common ops mixin to support a unified inteface datetimelike Index """ + @property + @Appender(Index.dt.__doc__) + def dt(self): + return self + def equals(self, other): """ Determines if two Index objects contain the same elements. diff --git a/pandas/tests/indexes/common.py b/pandas/tests/indexes/common.py index 81360bc0c13f9..446778b9cec98 100644 --- a/pandas/tests/indexes/common.py +++ b/pandas/tests/indexes/common.py @@ -1017,3 +1017,12 @@ def test_searchsorted_monotonic(self, indices): # non-monotonic should raise. with pytest.raises(ValueError): indices._searchsorted_monotonic(value, side='left') + + def test_dt_accessor(self): + # GH#17134 + index = self.create_index() + if isinstance(index, (DatetimeIndex, TimedeltaIndex, PeriodIndex)): + assert index.dt is index + else: + with pytest.raises(AttributeError): + index.dt