From 9d508caf4b182ec4522524be405281ad086c4c59 Mon Sep 17 00:00:00 2001 From: Brock Mendel Date: Sat, 29 Dec 2018 10:48:36 -0800 Subject: [PATCH 1/4] misc independent bits of 24024 --- pandas/core/groupby/groupby.py | 4 +-- pandas/core/indexes/base.py | 30 ------------------- pandas/core/indexes/datetimes.py | 3 +- pandas/tests/arithmetic/test_datetime64.py | 2 ++ .../tests/indexes/timedeltas/test_astype.py | 10 +++---- 5 files changed, 10 insertions(+), 39 deletions(-) diff --git a/pandas/core/groupby/groupby.py b/pandas/core/groupby/groupby.py index 60b6c843492c7..6a8221ce4ccfe 100644 --- a/pandas/core/groupby/groupby.py +++ b/pandas/core/groupby/groupby.py @@ -759,7 +759,7 @@ def _try_cast(self, result, obj, numeric_only=False): """ if obj.ndim > 1: - dtype = obj.values.dtype + dtype = obj._values.dtype else: dtype = obj.dtype @@ -768,7 +768,7 @@ def _try_cast(self, result, obj, numeric_only=False): # The function can return something of any type, so check # if the type is compatible with the calling EA. try: - result = obj.values._from_sequence(result) + result = obj._values._from_sequence(result, dtype=dtype) except Exception: # https://github.com/pandas-dev/pandas/issues/22850 # pandas has no control over what 3rd-party ExtensionArrays diff --git a/pandas/core/indexes/base.py b/pandas/core/indexes/base.py index 36bf4ba5d9851..07aec6a0d833f 100644 --- a/pandas/core/indexes/base.py +++ b/pandas/core/indexes/base.py @@ -602,36 +602,6 @@ def _shallow_copy_with_infer(self, values, **kwargs): pass return Index(values, **attributes) - def _deepcopy_if_needed(self, orig, copy=False): - """ - Make a copy of self if data coincides (in memory) with orig. - Subclasses should override this if self._base is not an ndarray. - - .. versionadded:: 0.19.0 - - Parameters - ---------- - orig : ndarray - other ndarray to compare self._data against - copy : boolean, default False - when False, do not run any check, just return self - - Returns - ------- - A copy of self if needed, otherwise self : Index - """ - if copy: - # Retrieve the "base objects", i.e. the original memory allocations - if not isinstance(orig, np.ndarray): - # orig is a DatetimeIndex - orig = orig.values - orig = orig if orig.base is None else orig.base - new = self._data if self._data.base is None else self._data.base - if orig is new: - return self.copy(deep=True) - - return self - def _update_inplace(self, result, **kwargs): # guard when called from IndexOpsMixin raise TypeError("Index can't be updated inplace") diff --git a/pandas/core/indexes/datetimes.py b/pandas/core/indexes/datetimes.py index 1e6daabcc0445..ee7538ccab35a 100644 --- a/pandas/core/indexes/datetimes.py +++ b/pandas/core/indexes/datetimes.py @@ -319,8 +319,7 @@ def __new__(cls, data=None, subarr = cls._simple_new(dtarr._data, name=name, freq=dtarr.freq, tz=dtarr.tz) - - return subarr._deepcopy_if_needed(ref_to_data, copy) + return subarr @classmethod def _simple_new(cls, values, name=None, freq=None, tz=None, dtype=None): diff --git a/pandas/tests/arithmetic/test_datetime64.py b/pandas/tests/arithmetic/test_datetime64.py index 3065785649359..848a5adb14e0c 100644 --- a/pandas/tests/arithmetic/test_datetime64.py +++ b/pandas/tests/arithmetic/test_datetime64.py @@ -1591,6 +1591,8 @@ def check(get_ser, test_ser): # with 'operate' (from core/ops.py) for the ops that are not # defined op = getattr(get_ser, op_str, None) + # Previously, _validate_for_numeric_binop in core/indexes/base.py + # did this for us. with pytest.raises(TypeError, match='operate|[cC]annot|unsupported operand'): op(test_ser) diff --git a/pandas/tests/indexes/timedeltas/test_astype.py b/pandas/tests/indexes/timedeltas/test_astype.py index 088322d9f9a97..0085b704f0a4e 100644 --- a/pandas/tests/indexes/timedeltas/test_astype.py +++ b/pandas/tests/indexes/timedeltas/test_astype.py @@ -88,12 +88,12 @@ def test_astype_raises(self, dtype): with pytest.raises(TypeError, match=msg): idx.astype(dtype) - @pytest.mark.parametrize('tz', [None, 'US/Central']) - def test_astype_category(self, tz): - obj = pd.date_range("2000", periods=2, tz=tz) + def test_astype_category(self): + obj = pd.timedelta_range("1H", periods=2, freq='H') + result = obj.astype('category') - expected = pd.CategoricalIndex([pd.Timestamp('2000-01-01', tz=tz), - pd.Timestamp('2000-01-02', tz=tz)]) + expected = pd.CategoricalIndex([pd.Timedelta('1H'), + pd.Timedelta('2H')]) tm.assert_index_equal(result, expected) # TODO: Use \._data following composition changeover From 016758d0ec295997fae62e053b16c519d6edbcad Mon Sep 17 00:00:00 2001 From: Brock Mendel Date: Sat, 29 Dec 2018 11:18:30 -0800 Subject: [PATCH 2/4] move shift back to DatetimeIndexOpsMixin --- pandas/core/arrays/datetimelike.py | 33 -------------------------- pandas/core/arrays/period.py | 27 ---------------------- pandas/core/indexes/datetimelike.py | 36 ++++++++++++++++++++++++++++- 3 files changed, 35 insertions(+), 61 deletions(-) diff --git a/pandas/core/arrays/datetimelike.py b/pandas/core/arrays/datetimelike.py index a6f603d16affe..f41b1418f60b8 100644 --- a/pandas/core/arrays/datetimelike.py +++ b/pandas/core/arrays/datetimelike.py @@ -1077,39 +1077,6 @@ def _addsub_offset_array(self, other, op): return type(self)(res_values, freq='infer') return self._from_sequence(res_values) - @deprecate_kwarg(old_arg_name='n', new_arg_name='periods') - def shift(self, periods, freq=None): - """ - Shift index by desired number of time frequency increments. - - This method is for shifting the values of datetime-like indexes - by a specified time increment a given number of times. - - Parameters - ---------- - periods : int - Number of periods (or increments) to shift by, - can be positive or negative. - - .. versionchanged:: 0.24.0 - - freq : pandas.DateOffset, pandas.Timedelta or string, optional - Frequency increment to shift by. - If None, the index is shifted by its own `freq` attribute. - Offset aliases are valid strings, e.g., 'D', 'W', 'M' etc. - - Returns - ------- - pandas.DatetimeIndex - Shifted index. - - See Also - -------- - Index.shift : Shift values of Index. - PeriodIndex.shift : Shift values of PeriodIndex. - """ - return self._time_shift(periods=periods, freq=freq) - def _time_shift(self, periods, freq=None): """ Shift each value by `periods`. diff --git a/pandas/core/arrays/period.py b/pandas/core/arrays/period.py index 5ff244b5fd7ae..3cd8b483416f9 100644 --- a/pandas/core/arrays/period.py +++ b/pandas/core/arrays/period.py @@ -435,33 +435,6 @@ def value_counts(self, dropna=False): # -------------------------------------------------------------------- - def shift(self, periods=1, fill_value=None): - """ - Shift values by desired number. - - Newly introduced missing values are filled with - ``self.dtype.na_value``. - - .. versionadded:: 0.24.0 - - Parameters - ---------- - periods : int, default 1 - The number of periods to shift. Negative values are allowed - for shifting backwards. - fill_value : optional, default NaT - - .. versionadded:: 0.24.0 - - Returns - ------- - shifted : PeriodArray - """ - # TODO(DatetimeArray): remove - # The semantics for Index.shift differ from EA.shift - # then just call super. - return ExtensionArray.shift(self, periods, fill_value=fill_value) - def _time_shift(self, n, freq=None): """ Shift each value by `periods`. diff --git a/pandas/core/indexes/datetimelike.py b/pandas/core/indexes/datetimelike.py index 3810f204185fd..419e610132df2 100644 --- a/pandas/core/indexes/datetimelike.py +++ b/pandas/core/indexes/datetimelike.py @@ -10,7 +10,7 @@ from pandas._libs import NaT, iNaT, lib from pandas.compat.numpy import function as nv from pandas.errors import AbstractMethodError -from pandas.util._decorators import Appender, cache_readonly +from pandas.util._decorators import Appender, cache_readonly, deprecate_kwarg from pandas.core.dtypes.common import ( ensure_int64, is_bool_dtype, is_dtype_equal, is_float, is_integer, @@ -581,6 +581,40 @@ def _time_shift(self, periods, freq=None): result = self._eadata._time_shift(periods, freq=freq) return type(self)(result, name=self.name) + @deprecate_kwarg(old_arg_name='n', new_arg_name='periods') + def shift(self, periods, freq=None): + """ + Shift index by desired number of time frequency increments. + + This method is for shifting the values of datetime-like indexes + by a specified time increment a given number of times. + + Parameters + ---------- + periods : int + Number of periods (or increments) to shift by, + can be positive or negative. + + .. versionchanged:: 0.24.0 + + freq : pandas.DateOffset, pandas.Timedelta or string, optional + Frequency increment to shift by. + If None, the index is shifted by its own `freq` attribute. + Offset aliases are valid strings, e.g., 'D', 'W', 'M' etc. + + Returns + ------- + pandas.DatetimeIndex + Shifted index. + + See Also + -------- + Index.shift : Shift values of Index. + PeriodIndex.shift : Shift values of PeriodIndex. + """ + result = self._eadata._time_shift(periods, freq=freq) + return type(self)(result, name=self.name) + def wrap_arithmetic_op(self, other, result): if result is NotImplemented: From 881676306c0767e7e9e995b83404147e035b537e Mon Sep 17 00:00:00 2001 From: Brock Mendel Date: Sat, 29 Dec 2018 13:28:01 -0800 Subject: [PATCH 3/4] remove unused variable --- pandas/core/indexes/datetimes.py | 6 ------ 1 file changed, 6 deletions(-) diff --git a/pandas/core/indexes/datetimes.py b/pandas/core/indexes/datetimes.py index c16936438236e..ffee263c0bedc 100644 --- a/pandas/core/indexes/datetimes.py +++ b/pandas/core/indexes/datetimes.py @@ -299,12 +299,6 @@ def __new__(cls, data=None, # - Cases checked above all return/raise before reaching here - # - # This allows to later ensure that the 'copy' parameter is honored: - if isinstance(data, Index): - ref_to_data = data._data - else: - ref_to_data = data - if name is None and hasattr(data, 'name'): name = data.name From bfebc52f9acf4dd5476f9edd40bb398401df8820 Mon Sep 17 00:00:00 2001 From: Brock Mendel Date: Sat, 29 Dec 2018 14:12:10 -0800 Subject: [PATCH 4/4] remove unused import --- pandas/core/arrays/datetimelike.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pandas/core/arrays/datetimelike.py b/pandas/core/arrays/datetimelike.py index f41b1418f60b8..870f913ecceb3 100644 --- a/pandas/core/arrays/datetimelike.py +++ b/pandas/core/arrays/datetimelike.py @@ -15,7 +15,7 @@ from pandas.compat.numpy import function as nv from pandas.errors import ( AbstractMethodError, NullFrequencyError, PerformanceWarning) -from pandas.util._decorators import Appender, Substitution, deprecate_kwarg +from pandas.util._decorators import Appender, Substitution from pandas.core.dtypes.common import ( is_bool_dtype, is_categorical_dtype, is_datetime64_any_dtype,