diff --git a/doc/source/whatsnew/v0.23.0.txt b/doc/source/whatsnew/v0.23.0.txt index 07e633ded942a..d7a3f0d077302 100644 --- a/doc/source/whatsnew/v0.23.0.txt +++ b/doc/source/whatsnew/v0.23.0.txt @@ -376,7 +376,8 @@ Conversion - Bug in :class:`Series` with ``dtype='timedelta64[ns]`` where addition or subtraction of ``TimedeltaIndex`` could return a ``Series`` with an incorrect name (issue:`19043`) - Fixed bug where comparing :class:`DatetimeIndex` failed to raise ``TypeError`` when attempting to compare timezone-aware and timezone-naive datetimelike objects (:issue:`18162`) - Bug in :class:`DatetimeIndex` where the repr was not showing high-precision time values at the end of a day (e.g., 23:59:59.999999999) (:issue:`19030`) - +- Bug where dividing a scalar timedelta-like object with :class:`TimedeltaIndex` performed the reciprocal operation (:issue:`19125`) +- Indexing ^^^^^^^^ diff --git a/pandas/core/indexes/base.py b/pandas/core/indexes/base.py index 55a26d57fa1d6..f634d809560ee 100644 --- a/pandas/core/indexes/base.py +++ b/pandas/core/indexes/base.py @@ -3861,7 +3861,7 @@ def dropna(self, how='any'): return self._shallow_copy(self.values[~self._isnan]) return self._shallow_copy() - def _evaluate_with_timedelta_like(self, other, op, opstr): + def _evaluate_with_timedelta_like(self, other, op, opstr, reversed=False): raise TypeError("can only perform ops with timedelta like values") def _evaluate_with_datetime_like(self, other, op, opstr): @@ -4025,7 +4025,8 @@ def _evaluate_numeric_binop(self, other): # handle time-based others if isinstance(other, (ABCDateOffset, np.timedelta64, Timedelta, datetime.timedelta)): - return self._evaluate_with_timedelta_like(other, op, opstr) + return self._evaluate_with_timedelta_like(other, op, opstr, + reversed) elif isinstance(other, (Timestamp, np.datetime64)): return self._evaluate_with_datetime_like(other, op, opstr) diff --git a/pandas/core/indexes/timedeltas.py b/pandas/core/indexes/timedeltas.py index ccedaa9cf71ee..12ca26cfe0266 100644 --- a/pandas/core/indexes/timedeltas.py +++ b/pandas/core/indexes/timedeltas.py @@ -372,7 +372,7 @@ def _add_delta(self, delta): result = TimedeltaIndex(new_values, freq='infer', name=name) return result - def _evaluate_with_timedelta_like(self, other, op, opstr): + def _evaluate_with_timedelta_like(self, other, op, opstr, reversed=False): if isinstance(other, ABCSeries): # GH#19042 return NotImplemented @@ -386,10 +386,14 @@ def _evaluate_with_timedelta_like(self, other, op, opstr): "division by pd.NaT not implemented") i8 = self.asi8 + left, right = i8, other.value + if reversed: + left, right = right, left + if opstr in ['__floordiv__']: - result = i8 // other.value + result = left // right else: - result = op(i8, float(other.value)) + result = op(left, float(right)) result = self._maybe_mask_results(result, convert='float64') return Index(result, name=self.name, copy=False) @@ -972,6 +976,7 @@ def _is_convertible_to_index(other): def _is_convertible_to_td(key): + # TODO: Not all DateOffset objects are convertible to Timedelta return isinstance(key, (DateOffset, timedelta, Timedelta, np.timedelta64, compat.string_types)) diff --git a/pandas/tests/indexes/timedeltas/test_arithmetic.py b/pandas/tests/indexes/timedeltas/test_arithmetic.py index 2581a8fad078a..3ec918e391860 100644 --- a/pandas/tests/indexes/timedeltas/test_arithmetic.py +++ b/pandas/tests/indexes/timedeltas/test_arithmetic.py @@ -286,6 +286,23 @@ def test_tdi_radd_timestamp(self): # ------------------------------------------------------------- + @pytest.mark.parametrize('scalar_td', [ + timedelta(minutes=10, seconds=7), + Timedelta('10m7s'), + Timedelta('10m7s').to_timedelta64()]) + def test_tdi_floordiv_timedelta_scalar(self, scalar_td): + # GH#19125 + tdi = TimedeltaIndex(['00:05:03', '00:05:03', pd.NaT], freq=None) + expected = pd.Index([2.0, 2.0, np.nan]) + + res = tdi.__rfloordiv__(scalar_td) + tm.assert_index_equal(res, expected) + + expected = pd.Index([0.0, 0.0, np.nan]) + + res = tdi // (scalar_td) + tm.assert_index_equal(res, expected) + # TODO: Split by operation, better name def test_ops_compat(self):