From 424764c9c16f0e548c696b5d51492e3119a4bff2 Mon Sep 17 00:00:00 2001 From: jbrockmendel Date: Tue, 31 Dec 2019 16:19:06 -0800 Subject: [PATCH 1/2] CLN: datetimelike EA and Index cleanups --- pandas/core/arrays/datetimes.py | 2 ++ pandas/core/arrays/period.py | 16 ++++++++-------- pandas/core/arrays/timedeltas.py | 3 +++ pandas/core/base.py | 2 +- pandas/core/indexes/datetimelike.py | 1 - pandas/core/indexes/datetimes.py | 7 ++----- pandas/core/indexes/period.py | 13 ------------- pandas/core/indexes/timedeltas.py | 9 ++++----- pandas/core/internals/blocks.py | 1 - 9 files changed, 20 insertions(+), 34 deletions(-) diff --git a/pandas/core/arrays/datetimes.py b/pandas/core/arrays/datetimes.py index eb762a23d684d..4010a0b9d6fc0 100644 --- a/pandas/core/arrays/datetimes.py +++ b/pandas/core/arrays/datetimes.py @@ -559,6 +559,8 @@ def _scalar_from_string(self, value): def _check_compatible_with(self, other): if other is NaT: return + if isinstance(other, (datetime, np.datetime64)): + other = Timestamp(other) if not timezones.tz_compare(self.tz, other.tz): raise ValueError(f"Timezones don't match. '{self.tz} != {other.tz}'") diff --git a/pandas/core/arrays/period.py b/pandas/core/arrays/period.py index df057ce5a0104..c5be958feb831 100644 --- a/pandas/core/arrays/period.py +++ b/pandas/core/arrays/period.py @@ -476,11 +476,6 @@ def to_timestamp(self, freq=None, how="start"): # -------------------------------------------------------------------- # Array-like / EA-Interface Methods - def _formatter(self, boxed=False): - if boxed: - return str - return "'{}'".format - @Appender(dtl.DatetimeLikeArrayMixin._validate_fill_value.__doc__) def _validate_fill_value(self, fill_value): if isna(fill_value): @@ -492,6 +487,9 @@ def _validate_fill_value(self, fill_value): raise ValueError(f"'fill_value' should be a Period. Got '{fill_value}'.") return fill_value + def _values_for_argsort(self): + return self._data + # -------------------------------------------------------------------- def _time_shift(self, periods, freq=None): @@ -582,6 +580,11 @@ def asfreq(self, freq=None, how="E"): # ------------------------------------------------------------------ # Rendering Methods + def _formatter(self, boxed=False): + if boxed: + return str + return "'{}'".format + def _format_native_types(self, na_rep="NaT", date_format=None, **kwargs): """ actually format my specific types @@ -774,9 +777,6 @@ def _check_timedeltalike_freq_compat(self, other): _raise_on_incompatible(self, other) - def _values_for_argsort(self): - return self._data - PeriodArray._add_comparison_ops() diff --git a/pandas/core/arrays/timedeltas.py b/pandas/core/arrays/timedeltas.py index b95dfc9ba7580..df9a0c418f9ae 100644 --- a/pandas/core/arrays/timedeltas.py +++ b/pandas/core/arrays/timedeltas.py @@ -378,6 +378,9 @@ def astype(self, dtype, copy=True): return self return dtl.DatetimeLikeArrayMixin.astype(self, dtype, copy=copy) + # ---------------------------------------------------------------- + # Reductions + def sum( self, axis=None, diff --git a/pandas/core/base.py b/pandas/core/base.py index 948b80fef4032..064a51bf0ce74 100644 --- a/pandas/core/base.py +++ b/pandas/core/base.py @@ -597,7 +597,7 @@ class IndexOpsMixin: # ndarray compatibility __array_priority__ = 1000 _deprecations: FrozenSet[str] = frozenset( - ["tolist", "item"] # tolist is not deprecated, just suppressed in the __dir__ + ["tolist"] # tolist is not deprecated, just suppressed in the __dir__ ) def transpose(self, *args, **kwargs): diff --git a/pandas/core/indexes/datetimelike.py b/pandas/core/indexes/datetimelike.py index 7ba04fc9d2fea..65bbb3d641fbf 100644 --- a/pandas/core/indexes/datetimelike.py +++ b/pandas/core/indexes/datetimelike.py @@ -122,7 +122,6 @@ class DatetimeIndexOpsMixin(ExtensionOpsMixin): ) resolution = cache_readonly(DatetimeLikeArrayMixin.resolution.fget) # type: ignore - _maybe_mask_results = ea_passthrough(DatetimeLikeArrayMixin._maybe_mask_results) __iter__ = ea_passthrough(DatetimeLikeArrayMixin.__iter__) mean = ea_passthrough(DatetimeLikeArrayMixin.mean) diff --git a/pandas/core/indexes/datetimes.py b/pandas/core/indexes/datetimes.py index 9ff968bc554e4..bad14fc869cd1 100644 --- a/pandas/core/indexes/datetimes.py +++ b/pandas/core/indexes/datetimes.py @@ -35,7 +35,6 @@ DatetimeIndexOpsMixin, DatetimelikeDelegateMixin, DatetimeTimedeltaMixin, - ea_passthrough, ) from pandas.core.indexes.numeric import Int64Index from pandas.core.ops import get_op_result_name @@ -1135,8 +1134,6 @@ def slice_indexer(self, start=None, end=None, step=None, kind=None): is_normalized = cache_readonly(DatetimeArray.is_normalized.fget) # type: ignore _resolution = cache_readonly(DatetimeArray._resolution.fget) # type: ignore - _has_same_tz = ea_passthrough(DatetimeArray._has_same_tz) - def __getitem__(self, key): result = self._data.__getitem__(key) if is_scalar(result): @@ -1200,8 +1197,8 @@ def insert(self, loc, item): if isinstance(item, (datetime, np.datetime64)): self._assert_can_do_op(item) - if not self._has_same_tz(item) and not isna(item): - raise ValueError("Passed item and index have different timezone") + self._data._check_compatible_with(item) + # check freq can be preserved on edge cases if self.size and self.freq is not None: if item is NaT: diff --git a/pandas/core/indexes/period.py b/pandas/core/indexes/period.py index 6465a0c1724af..56e5fc21bce97 100644 --- a/pandas/core/indexes/period.py +++ b/pandas/core/indexes/period.py @@ -20,7 +20,6 @@ ) from pandas.core.accessor import delegate_names -from pandas.core.algorithms import unique1d from pandas.core.arrays.period import PeriodArray, period_array, validate_dtype_freq from pandas.core.base import _shared_docs import pandas.core.common as com @@ -622,18 +621,6 @@ def _get_unique_index(self, dropna=False): res = res.dropna() return res - @Appender(Index.unique.__doc__) - def unique(self, level=None): - # override the Index.unique method for performance GH#23083 - if level is not None: - # this should never occur, but is retained to make the signature - # match Index.unique - self._validate_index_level(level) - - values = self._ndarray_values - result = unique1d(values) - return self._shallow_copy(result) - def get_loc(self, key, method=None, tolerance=None): """ Get integer location for requested label diff --git a/pandas/core/indexes/timedeltas.py b/pandas/core/indexes/timedeltas.py index 480a4ae34bfb7..156e5317c008b 100644 --- a/pandas/core/indexes/timedeltas.py +++ b/pandas/core/indexes/timedeltas.py @@ -30,7 +30,6 @@ DatetimeIndexOpsMixin, DatetimelikeDelegateMixin, DatetimeTimedeltaMixin, - ea_passthrough, ) from pandas.core.indexes.numeric import Int64Index from pandas.core.ops import get_op_result_name @@ -50,9 +49,12 @@ class TimedeltaDelegateMixin(DatetimelikeDelegateMixin): "__neg__", "__pos__", "__abs__", + "sum", + "std", + "median", ] _raw_properties = {"components"} - _raw_methods = {"to_pytimedelta"} + _raw_methods = {"to_pytimedelta", "sum", "std", "median"} @delegate_names( @@ -151,9 +153,6 @@ def _join_i8_wrapper(joinf, **kwargs): _datetimelike_ops = TimedeltaArray._datetimelike_ops _datetimelike_methods = TimedeltaArray._datetimelike_methods _other_ops = TimedeltaArray._other_ops - sum = ea_passthrough(TimedeltaArray.sum) - std = ea_passthrough(TimedeltaArray.std) - median = ea_passthrough(TimedeltaArray.median) # ------------------------------------------------------------------- # Constructors diff --git a/pandas/core/internals/blocks.py b/pandas/core/internals/blocks.py index 664f6ea75a3be..c507226054d2c 100644 --- a/pandas/core/internals/blocks.py +++ b/pandas/core/internals/blocks.py @@ -380,7 +380,6 @@ def apply(self, func, **kwargs): return nbs if not isinstance(result, Block): - # Exclude the 0-dim case so we can do reductions result = self.make_block(values=_block_shape(result, ndim=self.ndim)) return result From 3f3b0c4700f296186c84e1ef35aaaeeb0d4ad349 Mon Sep 17 00:00:00 2001 From: jbrockmendel Date: Tue, 31 Dec 2019 16:58:28 -0800 Subject: [PATCH 2/2] revert change that broke --- pandas/core/arrays/datetimes.py | 2 -- pandas/core/indexes/datetimes.py | 3 ++- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/pandas/core/arrays/datetimes.py b/pandas/core/arrays/datetimes.py index 4010a0b9d6fc0..eb762a23d684d 100644 --- a/pandas/core/arrays/datetimes.py +++ b/pandas/core/arrays/datetimes.py @@ -559,8 +559,6 @@ def _scalar_from_string(self, value): def _check_compatible_with(self, other): if other is NaT: return - if isinstance(other, (datetime, np.datetime64)): - other = Timestamp(other) if not timezones.tz_compare(self.tz, other.tz): raise ValueError(f"Timezones don't match. '{self.tz} != {other.tz}'") diff --git a/pandas/core/indexes/datetimes.py b/pandas/core/indexes/datetimes.py index bad14fc869cd1..1e9576f8bbb8e 100644 --- a/pandas/core/indexes/datetimes.py +++ b/pandas/core/indexes/datetimes.py @@ -1197,7 +1197,8 @@ def insert(self, loc, item): if isinstance(item, (datetime, np.datetime64)): self._assert_can_do_op(item) - self._data._check_compatible_with(item) + if not self._has_same_tz(item) and not isna(item): + raise ValueError("Passed item and index have different timezone") # check freq can be preserved on edge cases if self.size and self.freq is not None: