From e6463beb69461fc1b993991186db3448cc54d1b3 Mon Sep 17 00:00:00 2001 From: Brock Mendel Date: Sun, 11 Nov 2018 19:28:01 -0800 Subject: [PATCH 01/12] implement box_with_timedelta, assert_timedelta_array_equal, and minimal code changes to make tests pass --- pandas/core/arrays/timedeltas.py | 34 ++++++++++++++++++- pandas/core/indexes/base.py | 4 ++- pandas/core/indexes/timedeltas.py | 6 ++++ pandas/core/ops.py | 3 +- pandas/tests/arithmetic/conftest.py | 14 +++++++- pandas/tests/arithmetic/test_timedelta64.py | 36 ++++++++++++++++----- pandas/util/testing.py | 14 +++++++- 7 files changed, 98 insertions(+), 13 deletions(-) diff --git a/pandas/core/arrays/timedeltas.py b/pandas/core/arrays/timedeltas.py index 1f78e0c00bf00..b74bed3e1e617 100644 --- a/pandas/core/arrays/timedeltas.py +++ b/pandas/core/arrays/timedeltas.py @@ -1,5 +1,8 @@ # -*- coding: utf-8 -*- +from __future__ import division + from datetime import timedelta +import operator import warnings import numpy as np @@ -22,7 +25,8 @@ is_datetime64_dtype, is_list_like, ensure_int64) -from pandas.core.dtypes.generic import ABCSeries, ABCTimedeltaIndex +from pandas.core.dtypes.generic import ( + ABCDataFrame, ABCSeries, ABCTimedeltaIndex, ABCIndexClass) from pandas.core.dtypes.missing import isna import pandas.core.common as com @@ -107,8 +111,29 @@ def wrapper(self, other): return compat.set_function_name(wrapper, opname, cls) +def _wrap_tdi_op(op): + """ + Instead of re-implementing multiplication/division etc operations + in the Array class, for now we dispatch to the Timedelta implementations. + """ + def method(self, other): + if isinstance(other, (ABCSeries, ABCDataFrame, ABCIndexClass)): + return NotImplemented + + from pandas import TimedeltaIndex + obj = TimedeltaIndex(self) + result = op(obj, other) + if is_timedelta64_dtype(result): + return type(self)(result) + return np.array(result) + + method.__name__ = '__{name}__'.format(name=op.__name__) + return method + + class TimedeltaArrayMixin(dtl.DatetimeLikeArrayMixin): _typ = "timedeltaarray" + __array_priority__ = 1000 @property def _box_func(self): @@ -285,6 +310,13 @@ def _evaluate_with_timedelta_like(self, other, op): return NotImplemented + __mul__ = _wrap_tdi_op(operator.mul) + __rmul__ = __mul__ + __truediv__ = _wrap_tdi_op(operator.truediv) + + if compat.PY2: + __div__ = __truediv__ + # ---------------------------------------------------------------- # Conversion Methods - Vectorized analogues of Timedelta methods diff --git a/pandas/core/indexes/base.py b/pandas/core/indexes/base.py index 263de57d32f31..579db7989a844 100644 --- a/pandas/core/indexes/base.py +++ b/pandas/core/indexes/base.py @@ -19,6 +19,7 @@ ABCSeries, ABCDataFrame, ABCMultiIndex, ABCPeriodIndex, ABCTimedeltaIndex, ABCDatetimeIndex, + ABCTimedeltaArray, ABCDateOffset) from pandas.core.dtypes.missing import isna, array_equivalent from pandas.core.dtypes.cast import maybe_cast_to_integer_array @@ -123,7 +124,8 @@ def index_arithmetic_method(self, other): elif isinstance(other, ABCTimedeltaIndex): # Defer to subclass implementation return NotImplemented - elif isinstance(other, np.ndarray) and is_timedelta64_dtype(other): + elif (isinstance(other, (np.ndarray, ABCTimedeltaArray)) and + is_timedelta64_dtype(other)): # GH#22390; wrap in Series for op, this will in turn wrap in # TimedeltaIndex, but will correctly raise TypeError instead of # NullFrequencyError for add/sub ops diff --git a/pandas/core/indexes/timedeltas.py b/pandas/core/indexes/timedeltas.py index 35e17c7400892..e3c0c066982cd 100644 --- a/pandas/core/indexes/timedeltas.py +++ b/pandas/core/indexes/timedeltas.py @@ -236,6 +236,12 @@ def _format_native_types(self, na_rep=u'NaT', date_format=None, **kwargs): # ------------------------------------------------------------------- # Wrapping TimedeltaArray + __mul__ = Index.__mul__ + __rmul__ = Index.__rmul__ + __truediv__ = Index.__truediv__ + if compat.PY2: + __div__ = Index.__div__ + days = wrap_field_accessor(TimedeltaArrayMixin.days) seconds = wrap_field_accessor(TimedeltaArrayMixin.seconds) microseconds = wrap_field_accessor(TimedeltaArrayMixin.microseconds) diff --git a/pandas/core/ops.py b/pandas/core/ops.py index fbfdfb9c01237..b14115473354a 100644 --- a/pandas/core/ops.py +++ b/pandas/core/ops.py @@ -43,7 +43,8 @@ ABCSeries, ABCDataFrame, ABCPanel, ABCIndex, ABCIndexClass, - ABCSparseSeries, ABCSparseArray) + ABCSparseSeries, ABCSparseArray, + ABCTimedeltaArray) # ----------------------------------------------------------------------------- diff --git a/pandas/tests/arithmetic/conftest.py b/pandas/tests/arithmetic/conftest.py index 9ee5e05638978..0779dc53aeb97 100644 --- a/pandas/tests/arithmetic/conftest.py +++ b/pandas/tests/arithmetic/conftest.py @@ -5,7 +5,10 @@ import pandas as pd from pandas.compat import long -from pandas.core.arrays import PeriodArray, DatetimeArrayMixin as DatetimeArray +from pandas.core.arrays import ( + PeriodArray, + DatetimeArrayMixin as DatetimeArray, + TimedeltaArrayMixin as TimedeltaArray) @pytest.fixture(params=[1, np.array(1, dtype=np.int64)]) @@ -189,3 +192,12 @@ def box_with_datetime(request): Like `box`, but specific to datetime64 for also testing DatetimeArray """ return request.param + + +@pytest.fixture(params=[pd.Index, pd.Series, pd.DataFrame, TimedeltaArray], + ids=lambda x: x.__name__) +def box_with_timedelta(request): + """ + Like `box`, but specific to timedelta64 for also testing TimedeltaArray + """ + return request.param diff --git a/pandas/tests/arithmetic/test_timedelta64.py b/pandas/tests/arithmetic/test_timedelta64.py index 58c8b3b07f723..c2e095b6a870f 100644 --- a/pandas/tests/arithmetic/test_timedelta64.py +++ b/pandas/tests/arithmetic/test_timedelta64.py @@ -16,6 +16,20 @@ timedelta_range, Timedelta, Timestamp, NaT, Series, TimedeltaIndex, DatetimeIndex, DataFrame) +from pandas.core.arrays import TimedeltaArrayMixin as TimedeltaArray + + +def get_upcast_box(box, vector): + """ + Given two box-types, find the one that takes priority + """ + if box is DataFrame or isinstance(vector, DataFrame): + return DataFrame + if box is Series or isinstance(vector, Series): + return Series + if box is pd.Index or isinstance(vector, pd.Index): + return pd.Index + return box # ------------------------------------------------------------------ @@ -1279,19 +1293,20 @@ def test_td64arr_div_numeric_scalar(self, box, two, tdser): Series([20, 30, 40])], ids=lambda x: type(x).__name__) @pytest.mark.parametrize('op', [operator.mul, ops.rmul]) - def test_td64arr_rmul_numeric_array(self, op, box, + def test_td64arr_rmul_numeric_array(self, op, box_with_timedelta, vector, dtype, tdser): # GH#4521 # divide/multiply by integers + box = box_with_timedelta + xbox = get_upcast_box(box, vector) + vector = vector.astype(dtype) expected = Series(['1180 Days', '1770 Days', 'NaT'], dtype='timedelta64[ns]') tdser = tm.box_expected(tdser, box) - # TODO: Make this up-casting more systematic? - box = Series if (box is pd.Index and type(vector) is Series) else box - expected = tm.box_expected(expected, box) + expected = tm.box_expected(expected, xbox) result = op(vector, tdser) tm.assert_equal(result, expected) @@ -1303,16 +1318,19 @@ def test_td64arr_rmul_numeric_array(self, op, box, pd.Index([20, 30, 40]), Series([20, 30, 40])], ids=lambda x: type(x).__name__) - def test_td64arr_div_numeric_array(self, box, vector, dtype, tdser): + def test_td64arr_div_numeric_array(self, box_with_timedelta, + vector, dtype, tdser): # GH#4521 # divide/multiply by integers + box = box_with_timedelta + xbox = get_upcast_box(box, vector) + vector = vector.astype(dtype) expected = Series(['2.95D', '1D 23H 12m', 'NaT'], dtype='timedelta64[ns]') tdser = tm.box_expected(tdser, box) - box = Series if (box is pd.Index and type(vector) is Series) else box - expected = tm.box_expected(expected, box) + expected = tm.box_expected(expected, xbox) result = tdser / vector tm.assert_equal(result, expected) @@ -1376,7 +1394,9 @@ def test_float_series_rdiv_td64arr(self, box, names): class TestTimedeltaArraylikeInvalidArithmeticOps(object): - def test_td64arr_pow_invalid(self, scalar_td, box): + def test_td64arr_pow_invalid(self, scalar_td, box_with_timedelta): + box = box_with_timedelta + td1 = Series([timedelta(minutes=5, seconds=3)] * 3) td1.iloc[2] = np.nan diff --git a/pandas/util/testing.py b/pandas/util/testing.py index 1fa77f5321038..a0901a4c1ee4b 100644 --- a/pandas/util/testing.py +++ b/pandas/util/testing.py @@ -37,7 +37,7 @@ from pandas.core.algorithms import take_1d from pandas.core.arrays import ( DatetimeArrayMixin as DatetimeArray, ExtensionArray, IntervalArray, - PeriodArray, period_array) + PeriodArray, period_array, TimedeltaArrayMixin as TimedeltaArray) import pandas.core.common as com from pandas.io.common import urlopen @@ -1080,6 +1080,14 @@ def assert_datetime_array_equal(left, right, obj='DatetimeArray'): assert_attr_equal('tz', left, right, obj=obj) +def assert_timedelta_array_equal(left, right, obj='TimedeltaArray'): + _check_isinstance(left, right, TimedeltaArray) + + assert_numpy_array_equal(left._data, right._data, + obj='{obj}._data'.format(obj=obj)) + assert_attr_equal('freq', left, right, obj=obj) + + def raise_assert_detail(obj, message, left, right, diff=None): __tracebackhide__ = True @@ -1579,6 +1587,8 @@ def assert_equal(left, right, **kwargs): assert_period_array_equal(left, right, **kwargs) elif isinstance(left, DatetimeArray): assert_datetime_array_equal(left, right, **kwargs) + elif isinstance(left, TimedeltaArray): + assert_timedelta_array_equal(left, right, **kwargs) elif isinstance(left, ExtensionArray): assert_extension_array_equal(left, right, **kwargs) elif isinstance(left, np.ndarray): @@ -1616,6 +1626,8 @@ def box_expected(expected, box_cls, transpose=True): expected = period_array(expected) elif box_cls is DatetimeArray: expected = DatetimeArray(expected) + elif box_cls is TimedeltaArray: + expected = TimedeltaArray(expected) elif box_cls is np.ndarray: expected = np.array(expected) else: From f5a7891a0f7d3baade0fdddad3b19e5eddebf6cb Mon Sep 17 00:00:00 2001 From: Brock Mendel Date: Sun, 11 Nov 2018 19:53:57 -0800 Subject: [PATCH 02/12] extend tests for floordiv --- pandas/core/arrays/timedeltas.py | 3 + pandas/tests/arithmetic/test_timedelta64.py | 64 +++++++++++++++------ 2 files changed, 50 insertions(+), 17 deletions(-) diff --git a/pandas/core/arrays/timedeltas.py b/pandas/core/arrays/timedeltas.py index b74bed3e1e617..9b7edb1be8010 100644 --- a/pandas/core/arrays/timedeltas.py +++ b/pandas/core/arrays/timedeltas.py @@ -31,6 +31,7 @@ import pandas.core.common as com from pandas.core.algorithms import checked_add_with_arr +from pandas.core import ops from pandas.tseries.offsets import Tick from pandas.tseries.frequencies import to_offset @@ -313,6 +314,8 @@ def _evaluate_with_timedelta_like(self, other, op): __mul__ = _wrap_tdi_op(operator.mul) __rmul__ = __mul__ __truediv__ = _wrap_tdi_op(operator.truediv) + __floordiv__ = _wrap_tdi_op(operator.floordiv) + __rfloordiv__ = _wrap_tdi_op(ops.rfloordiv) if compat.PY2: __div__ = __truediv__ diff --git a/pandas/tests/arithmetic/test_timedelta64.py b/pandas/tests/arithmetic/test_timedelta64.py index c2e095b6a870f..d3195a299de39 100644 --- a/pandas/tests/arithmetic/test_timedelta64.py +++ b/pandas/tests/arithmetic/test_timedelta64.py @@ -1134,59 +1134,75 @@ def test_tdi_div_tdlike_scalar_with_nat(self, two_hours, box): # ------------------------------------------------------------------ # __floordiv__, __rfloordiv__ - def test_td64arr_floordiv_tdscalar(self, box, scalar_td): + def test_td64arr_floordiv_tdscalar(self, box_with_timedelta, scalar_td): # GH#18831 + box = box_with_timedelta + xbox = box if box is not TimedeltaArray else np.ndarray + td1 = Series([timedelta(minutes=5, seconds=3)] * 3) td1.iloc[2] = np.nan expected = Series([0, 0, np.nan]) td1 = tm.box_expected(td1, box, transpose=False) - expected = tm.box_expected(expected, box, transpose=False) + expected = tm.box_expected(expected, xbox, transpose=False) result = td1 // scalar_td tm.assert_equal(result, expected) - def test_td64arr_rfloordiv_tdscalar(self, box, scalar_td): + def test_td64arr_rfloordiv_tdscalar(self, box_with_timedelta, scalar_td): # GH#18831 + box = box_with_timedelta + xbox = box if box is not TimedeltaArray else np.ndarray + td1 = Series([timedelta(minutes=5, seconds=3)] * 3) td1.iloc[2] = np.nan expected = Series([1, 1, np.nan]) td1 = tm.box_expected(td1, box, transpose=False) - expected = tm.box_expected(expected, box, transpose=False) + expected = tm.box_expected(expected, xbox, transpose=False) result = scalar_td // td1 tm.assert_equal(result, expected) - def test_td64arr_rfloordiv_tdscalar_explicit(self, box, scalar_td): + def test_td64arr_rfloordiv_tdscalar_explicit(self, box_with_timedelta, + scalar_td): # GH#18831 + box = box_with_timedelta + xbox = box if box is not TimedeltaArray else np.ndarray + td1 = Series([timedelta(minutes=5, seconds=3)] * 3) td1.iloc[2] = np.nan expected = Series([1, 1, np.nan]) td1 = tm.box_expected(td1, box, transpose=False) - expected = tm.box_expected(expected, box, transpose=False) + expected = tm.box_expected(expected, xbox, transpose=False) # We can test __rfloordiv__ using this syntax, # see `test_timedelta_rfloordiv` result = td1.__rfloordiv__(scalar_td) tm.assert_equal(result, expected) - def test_td64arr_floordiv_int(self, box): + def test_td64arr_floordiv_int(self, box_with_timedelta): + box = box_with_timedelta + idx = TimedeltaIndex(np.arange(5, dtype='int64')) idx = tm.box_expected(idx, box) result = idx // 1 tm.assert_equal(result, idx) - def test_td64arr_floordiv_tdlike_scalar(self, two_hours, box): + def test_td64arr_floordiv_tdlike_scalar(self, two_hours, + box_with_timedelta): + box = box_with_timedelta + xbox = box if box is not TimedeltaArray else np.ndarray + tdi = timedelta_range('1 days', '10 days', name='foo') expected = pd.Int64Index((np.arange(10) + 1) * 12, name='foo') tdi = tm.box_expected(tdi, box) - expected = tm.box_expected(expected, box) + expected = tm.box_expected(expected, xbox) result = tdi // two_hours tm.assert_equal(result, expected) @@ -1197,19 +1213,23 @@ def test_td64arr_floordiv_tdlike_scalar(self, two_hours, box): Timedelta('10m7s'), Timedelta('10m7s').to_timedelta64() ], ids=lambda x: type(x).__name__) - def test_td64arr_rfloordiv_tdlike_scalar(self, scalar_td, box): + def test_td64arr_rfloordiv_tdlike_scalar(self, scalar_td, + box_with_timedelta): # GH#19125 + box = box_with_timedelta + xbox = box if box is not TimedeltaArray else np.ndarray + tdi = TimedeltaIndex(['00:05:03', '00:05:03', pd.NaT], freq=None) expected = pd.Index([2.0, 2.0, np.nan]) tdi = tm.box_expected(tdi, box, transpose=False) - expected = tm.box_expected(expected, box, transpose=False) + expected = tm.box_expected(expected, xbox, transpose=False) res = tdi.__rfloordiv__(scalar_td) tm.assert_equal(res, expected) expected = pd.Index([0.0, 0.0, np.nan]) - expected = tm.box_expected(expected, box, transpose=False) + expected = tm.box_expected(expected, xbox, transpose=False) res = tdi // (scalar_td) tm.assert_equal(res, expected) @@ -1217,7 +1237,9 @@ def test_td64arr_rfloordiv_tdlike_scalar(self, scalar_td, box): # ------------------------------------------------------------------ # Operations with invalid others - def test_td64arr_mul_tdscalar_invalid(self, box, scalar_td): + def test_td64arr_mul_tdscalar_invalid(self, box_with_timedelta, scalar_td): + box = box_with_timedelta + td1 = Series([timedelta(minutes=5, seconds=3)] * 3) td1.iloc[2] = np.nan @@ -1232,7 +1254,9 @@ def test_td64arr_mul_tdscalar_invalid(self, box, scalar_td): with pytest.raises(TypeError, match=pattern): scalar_td * td1 - def test_td64arr_mul_too_short_raises(self, box): + def test_td64arr_mul_too_short_raises(self, box_with_timedelta): + box = box_with_timedelta + idx = TimedeltaIndex(np.arange(5, dtype='int64')) idx = tm.box_expected(idx, box) with pytest.raises(TypeError): @@ -1240,7 +1264,9 @@ def test_td64arr_mul_too_short_raises(self, box): with pytest.raises(ValueError): idx * np.array([1, 2]) - def test_td64arr_mul_td64arr_raises(self, box): + def test_td64arr_mul_td64arr_raises(self, box_with_timedelta): + box = box_with_timedelta + idx = TimedeltaIndex(np.arange(5, dtype='int64')) idx = tm.box_expected(idx, box) with pytest.raises(TypeError): @@ -1250,9 +1276,11 @@ def test_td64arr_mul_td64arr_raises(self, box): # Operations with numeric others @pytest.mark.parametrize('one', [1, np.array(1), 1.0, np.array(1.0)]) - def test_td64arr_mul_numeric_scalar(self, box, one, tdser): + def test_td64arr_mul_numeric_scalar(self, box_with_timedelta, one, tdser): # GH#4521 # divide/multiply by integers + box = box_with_timedelta + expected = Series(['-59 Days', '-59 Days', 'NaT'], dtype='timedelta64[ns]') @@ -1274,9 +1302,11 @@ def test_td64arr_mul_numeric_scalar(self, box, one, tdser): tm.assert_equal(result, expected) @pytest.mark.parametrize('two', [2, 2.0, np.array(2), np.array(2.0)]) - def test_td64arr_div_numeric_scalar(self, box, two, tdser): + def test_td64arr_div_numeric_scalar(self, box_with_timedelta, two, tdser): # GH#4521 # divide/multiply by integers + box = box_with_timedelta + expected = Series(['29.5D', '29.5D', 'NaT'], dtype='timedelta64[ns]') tdser = tm.box_expected(tdser, box) From 291dd516c7c0950865bd0afb53c338a2b47edb65 Mon Sep 17 00:00:00 2001 From: Brock Mendel Date: Sun, 11 Nov 2018 20:00:24 -0800 Subject: [PATCH 03/12] extend tests to multiplication --- pandas/tests/arithmetic/test_timedelta64.py | 64 +++++++++++++++------ 1 file changed, 45 insertions(+), 19 deletions(-) diff --git a/pandas/tests/arithmetic/test_timedelta64.py b/pandas/tests/arithmetic/test_timedelta64.py index d3195a299de39..00f7264e11205 100644 --- a/pandas/tests/arithmetic/test_timedelta64.py +++ b/pandas/tests/arithmetic/test_timedelta64.py @@ -1011,7 +1011,9 @@ def test_timedelta64_conversions(self, m, unit): # Multiplication # organized with scalar others first, then array-like - def test_td64arr_mul_int(self, box): + def test_td64arr_mul_int(self, box_with_timedelta): + box = box_with_timedelta + idx = TimedeltaIndex(np.arange(5, dtype='int64')) idx = tm.box_expected(idx, box) @@ -1021,13 +1023,18 @@ def test_td64arr_mul_int(self, box): result = 1 * idx tm.assert_equal(result, idx) - def test_td64arr_mul_tdlike_scalar_raises(self, two_hours, box): + def test_td64arr_mul_tdlike_scalar_raises(self, two_hours, + box_with_timedelta): + box = box_with_timedelta + rng = timedelta_range('1 days', '10 days', name='foo') rng = tm.box_expected(rng, box) with pytest.raises(TypeError): rng * two_hours - def test_tdi_mul_int_array_zerodim(self, box): + def test_tdi_mul_int_array_zerodim(self, box_with_timedelta): + box = box_with_timedelta + rng5 = np.arange(5, dtype='int64') idx = TimedeltaIndex(rng5) expected = TimedeltaIndex(rng5 * 5) @@ -1038,7 +1045,9 @@ def test_tdi_mul_int_array_zerodim(self, box): result = idx * np.array(5, dtype='int64') tm.assert_equal(result, expected) - def test_tdi_mul_int_array(self, box): + def test_tdi_mul_int_array(self, box_with_timedelta): + box = box_with_timedelta + rng5 = np.arange(5, dtype='int64') idx = TimedeltaIndex(rng5) expected = TimedeltaIndex(rng5 ** 2) @@ -1049,26 +1058,29 @@ def test_tdi_mul_int_array(self, box): result = idx * rng5 tm.assert_equal(result, expected) - def test_tdi_mul_int_series(self, box): + def test_tdi_mul_int_series(self, box_with_timedelta): + box = box_with_timedelta + xbox = pd.Series if box in [pd.Index, TimedeltaArray] else box + idx = TimedeltaIndex(np.arange(5, dtype='int64')) expected = TimedeltaIndex(np.arange(5, dtype='int64') ** 2) idx = tm.box_expected(idx, box) - - box2 = pd.Series if box is pd.Index else box - expected = tm.box_expected(expected, box2) + expected = tm.box_expected(expected, xbox) result = idx * pd.Series(np.arange(5, dtype='int64')) tm.assert_equal(result, expected) - def test_tdi_mul_float_series(self, box): + def test_tdi_mul_float_series(self, box_with_timedelta): + box = box_with_timedelta + xbox = pd.Series if box in [pd.Index, TimedeltaArray] else box + idx = TimedeltaIndex(np.arange(5, dtype='int64')) idx = tm.box_expected(idx, box) rng5f = np.arange(5, dtype='float64') expected = TimedeltaIndex(rng5f * (rng5f + 1.0)) - box2 = pd.Series if box is pd.Index else box - expected = tm.box_expected(expected, box2) + expected = tm.box_expected(expected, xbox) result = idx * Series(rng5f + 1.0) tm.assert_equal(result, expected) @@ -1081,12 +1093,15 @@ def test_tdi_mul_float_series(self, box): pd.Float64Index(range(1, 11)), pd.RangeIndex(1, 11) ], ids=lambda x: type(x).__name__) - def test_tdi_rmul_arraylike(self, other, box): + def test_tdi_rmul_arraylike(self, other, box_with_timedelta): + box = box_with_timedelta + xbox = get_upcast_box(box, other) + tdi = TimedeltaIndex(['1 Day'] * 10) expected = timedelta_range('1 days', '10 days') tdi = tm.box_expected(tdi, box) - expected = tm.box_expected(expected, box) + expected = tm.box_expected(expected, xbox) result = other * tdi tm.assert_equal(result, expected) @@ -1096,37 +1111,48 @@ def test_tdi_rmul_arraylike(self, other, box): # ------------------------------------------------------------------ # __div__ - def test_td64arr_div_nat_invalid(self, box): + def test_td64arr_div_nat_invalid(self, box_with_timedelta): # don't allow division by NaT (maybe could in the future) + box = box_with_timedelta + rng = timedelta_range('1 days', '10 days', name='foo') rng = tm.box_expected(rng, box) with pytest.raises(TypeError): rng / pd.NaT - def test_td64arr_div_int(self, box): + def test_td64arr_div_int(self, box_with_timedelta): + box = box_with_timedelta + idx = TimedeltaIndex(np.arange(5, dtype='int64')) idx = tm.box_expected(idx, box) result = idx / 1 tm.assert_equal(result, idx) - def test_tdi_div_tdlike_scalar(self, two_hours, box): + def test_tdi_div_tdlike_scalar(self, two_hours, box_with_timedelta): # GH#20088, GH#22163 ensure DataFrame returns correct dtype + box = box_with_timedelta + xbox = box if box is not TimedeltaArray else np.ndarray + rng = timedelta_range('1 days', '10 days', name='foo') expected = pd.Float64Index((np.arange(10) + 1) * 12, name='foo') rng = tm.box_expected(rng, box) - expected = tm.box_expected(expected, box) + expected = tm.box_expected(expected, xbox) result = rng / two_hours tm.assert_equal(result, expected) - def test_tdi_div_tdlike_scalar_with_nat(self, two_hours, box): + def test_tdi_div_tdlike_scalar_with_nat(self, two_hours, + box_with_timedelta): + box = box_with_timedelta + xbox = box if box is not TimedeltaArray else np.ndarray + rng = TimedeltaIndex(['1 days', pd.NaT, '2 days'], name='foo') expected = pd.Float64Index([12, np.nan, 24], name='foo') rng = tm.box_expected(rng, box) - expected = tm.box_expected(expected, box) + expected = tm.box_expected(expected, xbox) result = rng / two_hours tm.assert_equal(result, expected) From 52319fd8eab50ffd7a00fec59dad10444408e5d2 Mon Sep 17 00:00:00 2001 From: Brock Mendel Date: Mon, 12 Nov 2018 06:45:21 -0800 Subject: [PATCH 04/12] extend tests for floordiv --- pandas/core/arrays/timedeltas.py | 6 +++ pandas/core/indexes/timedeltas.py | 2 + pandas/tests/arithmetic/test_timedelta64.py | 59 ++++++++++++++------- 3 files changed, 49 insertions(+), 18 deletions(-) diff --git a/pandas/core/arrays/timedeltas.py b/pandas/core/arrays/timedeltas.py index 9b7edb1be8010..b18e05b07ce45 100644 --- a/pandas/core/arrays/timedeltas.py +++ b/pandas/core/arrays/timedeltas.py @@ -320,6 +320,12 @@ def _evaluate_with_timedelta_like(self, other, op): if compat.PY2: __div__ = __truediv__ + # Note: TimedeltaIndex overrides this in call to cls._add_numeric_methods + def __neg__(self): + if self.freq is not None: + return type(self)(-self._data, freq=-self.freq) + return type(self)(-self._data) + # ---------------------------------------------------------------- # Conversion Methods - Vectorized analogues of Timedelta methods diff --git a/pandas/core/indexes/timedeltas.py b/pandas/core/indexes/timedeltas.py index e3c0c066982cd..adde7bbef1335 100644 --- a/pandas/core/indexes/timedeltas.py +++ b/pandas/core/indexes/timedeltas.py @@ -239,6 +239,8 @@ def _format_native_types(self, na_rep=u'NaT', date_format=None, **kwargs): __mul__ = Index.__mul__ __rmul__ = Index.__rmul__ __truediv__ = Index.__truediv__ + __floordiv__ = Index.__floordiv__ + __rfloordiv__ = Index.__rfloordiv__ if compat.PY2: __div__ = Index.__div__ diff --git a/pandas/tests/arithmetic/test_timedelta64.py b/pandas/tests/arithmetic/test_timedelta64.py index 00f7264e11205..52206ab8daf6d 100644 --- a/pandas/tests/arithmetic/test_timedelta64.py +++ b/pandas/tests/arithmetic/test_timedelta64.py @@ -16,7 +16,9 @@ timedelta_range, Timedelta, Timestamp, NaT, Series, TimedeltaIndex, DatetimeIndex, DataFrame) -from pandas.core.arrays import TimedeltaArrayMixin as TimedeltaArray +from pandas.core.arrays import ( + TimedeltaArrayMixin as TimedeltaArray, + DatetimeArrayMixin as DatetimeArray) def get_upcast_box(box, vector): @@ -366,8 +368,10 @@ def test_timedelta64_ops_nat(self): # ------------------------------------------------------------- # Invalid Operations - def test_td64arr_add_str_invalid(self, box): + def test_td64arr_add_str_invalid(self, box_with_timedelta): # GH#13624 + box = box_with_timedelta + tdi = TimedeltaIndex(['1 day', '2 days']) tdi = tm.box_expected(tdi, box) @@ -380,7 +384,9 @@ def test_td64arr_add_str_invalid(self, box): @pytest.mark.parametrize('op', [operator.add, ops.radd, operator.sub, ops.rsub], ids=lambda x: x.__name__) - def test_td64arr_add_sub_float(self, box, op, other): + def test_td64arr_add_sub_float(self, box_with_timedelta, op, other): + box = box_with_timedelta + tdi = TimedeltaIndex(['-1 days', '-1 days']) tdi = tm.box_expected(tdi, box) @@ -388,9 +394,11 @@ def test_td64arr_add_sub_float(self, box, op, other): op(tdi, other) @pytest.mark.parametrize('freq', [None, 'H']) - def test_td64arr_sub_period(self, box, freq): + def test_td64arr_sub_period(self, box_with_timedelta, freq): # GH#13078 # not supported, check TypeError + box = box_with_timedelta + p = pd.Period('2011-01-01', freq='D') idx = TimedeltaIndex(['1 hours', '2 hours'], freq=freq) idx = tm.box_expected(idx, box) @@ -403,8 +411,10 @@ def test_td64arr_sub_period(self, box, freq): @pytest.mark.parametrize('pi_freq', ['D', 'W', 'Q', 'H']) @pytest.mark.parametrize('tdi_freq', [None, 'H']) - def test_td64arr_sub_pi(self, box, tdi_freq, pi_freq): + def test_td64arr_sub_pi(self, box_with_timedelta, tdi_freq, pi_freq): # GH#20049 subtracting PeriodIndex should raise TypeError + box = box_with_timedelta + tdi = TimedeltaIndex(['1 hours', '2 hours'], freq=tdi_freq) dti = Timestamp('2018-03-07 17:16:40') + tdi pi = dti.to_period(pi_freq) @@ -417,7 +427,9 @@ def test_td64arr_sub_pi(self, box, tdi_freq, pi_freq): # ------------------------------------------------------------- # Binary operations td64 arraylike and datetime-like - def test_td64arr_sub_timestamp_raises(self, box): + def test_td64arr_sub_timestamp_raises(self, box_with_timedelta): + box = box_with_timedelta + idx = TimedeltaIndex(['1 day', '2 day']) idx = tm.box_expected(idx, box) @@ -427,8 +439,11 @@ def test_td64arr_sub_timestamp_raises(self, box): with pytest.raises(TypeError, match=msg): idx - Timestamp('2011-01-01') - def test_td64arr_add_timestamp(self, box, tz_naive_fixture): + def test_td64arr_add_timestamp(self, box_with_timedelta, tz_naive_fixture): # GH#23215 + box = box_with_timedelta + xbox = box if box is not TimedeltaArray else DatetimeArray + # TODO: parametrize over scalar datetime types? tz = tz_naive_fixture other = Timestamp('2011-01-01', tz=tz) @@ -439,7 +454,7 @@ def test_td64arr_add_timestamp(self, box, tz_naive_fixture): # FIXME: fails with transpose=True because of tz-aware DataFrame # transpose bug idx = tm.box_expected(idx, box, transpose=False) - expected = tm.box_expected(expected, box, transpose=False) + expected = tm.box_expected(expected, xbox, transpose=False) result = idx + other tm.assert_equal(result, expected) @@ -452,8 +467,8 @@ def test_td64arr_add_sub_timestamp(self, box): ts = Timestamp('2012-01-01') # TODO: parametrize over types of datetime scalar? - tdser = Series(timedelta_range('1 day', periods=3)) - expected = Series(pd.date_range('2012-01-02', periods=3)) + tdser = timedelta_range('1 day', periods=3) + expected = pd.date_range('2012-01-02', periods=3) tdser = tm.box_expected(tdser, box) expected = tm.box_expected(expected, box) @@ -461,8 +476,7 @@ def test_td64arr_add_sub_timestamp(self, box): tm.assert_equal(ts + tdser, expected) tm.assert_equal(tdser + ts, expected) - expected2 = Series(pd.date_range('2011-12-31', - periods=3, freq='-1D')) + expected2 = pd.date_range('2011-12-31', periods=3, freq='-1D') expected2 = tm.box_expected(expected2, box) tm.assert_equal(ts - tdser, expected2) @@ -471,14 +485,17 @@ def test_td64arr_add_sub_timestamp(self, box): with pytest.raises(TypeError): tdser - ts - def test_tdi_sub_dt64_array(self, box): + def test_tdi_sub_dt64_array(self, box_with_timedelta): + box = box_with_timedelta + xbox = box if box is not TimedeltaArray else DatetimeArray + dti = pd.date_range('2016-01-01', periods=3) tdi = dti - dti.shift(1) dtarr = dti.values expected = pd.DatetimeIndex(dtarr) - tdi tdi = tm.box_expected(tdi, box) - expected = tm.box_expected(expected, box) + expected = tm.box_expected(expected, xbox) with pytest.raises(TypeError): tdi - dtarr @@ -487,29 +504,35 @@ def test_tdi_sub_dt64_array(self, box): result = dtarr - tdi tm.assert_equal(result, expected) - def test_tdi_add_dt64_array(self, box): + def test_tdi_add_dt64_array(self, box_with_timedelta): + box = box_with_timedelta + xbox = box if box is not TimedeltaArray else DatetimeArray + dti = pd.date_range('2016-01-01', periods=3) tdi = dti - dti.shift(1) dtarr = dti.values expected = pd.DatetimeIndex(dtarr) + tdi tdi = tm.box_expected(tdi, box) - expected = tm.box_expected(expected, box) + expected = tm.box_expected(expected, xbox) result = tdi + dtarr tm.assert_equal(result, expected) result = dtarr + tdi tm.assert_equal(result, expected) - def test_td64arr_add_datetime64_nat(self, box): + def test_td64arr_add_datetime64_nat(self, box_with_timedelta): # GH#23215 + box = box_with_timedelta + xbox = box if box is not TimedeltaArray else pd.Index + other = np.datetime64('NaT') tdi = timedelta_range('1 day', periods=3) expected = pd.DatetimeIndex(["NaT", "NaT", "NaT"]) tdser = tm.box_expected(tdi, box) - expected = tm.box_expected(expected, box) + expected = tm.box_expected(expected, xbox) tm.assert_equal(tdser + other, expected) tm.assert_equal(other + tdser, expected) From 0b217973d1fe939628610f2f90cf29ca7cd64bf1 Mon Sep 17 00:00:00 2001 From: Brock Mendel Date: Mon, 12 Nov 2018 10:04:33 -0800 Subject: [PATCH 05/12] extend tests to int/float --- pandas/tests/arithmetic/test_timedelta64.py | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/pandas/tests/arithmetic/test_timedelta64.py b/pandas/tests/arithmetic/test_timedelta64.py index 52206ab8daf6d..8836551cb967f 100644 --- a/pandas/tests/arithmetic/test_timedelta64.py +++ b/pandas/tests/arithmetic/test_timedelta64.py @@ -554,11 +554,16 @@ def test_td64arr_add_int_series_invalid(self, box, tdser): with pytest.raises(err): int_ser - tdser - def test_td64arr_add_intlike(self, box): + def test_td64arr_add_intlike(self, box_with_timedelta): # GH#19123 + box = box_with_timedelta + tdi = TimedeltaIndex(['59 days', '59 days', 'NaT']) ser = tm.box_expected(tdi, box) - err = TypeError if box is not pd.Index else NullFrequencyError + + err = TypeError + if box in [pd.Index, TimedeltaArray]: + err = NullFrequencyError other = Series([20, 30, 40], dtype='uint8') @@ -584,10 +589,13 @@ def test_td64arr_add_intlike(self, box): ser - pd.Index(other) @pytest.mark.parametrize('scalar', [1, 1.5, np.array(2)]) - def test_td64arr_add_sub_numeric_scalar_invalid(self, box, scalar, tdser): + def test_td64arr_add_sub_numeric_scalar_invalid(self, box_with_timedelta, + scalar, tdser): + box = box_with_timedelta + tdser = tm.box_expected(tdser, box) err = TypeError - if box is pd.Index and not isinstance(scalar, float): + if box in [pd.Index, TimedeltaArray] and not isinstance(scalar, float): err = NullFrequencyError with pytest.raises(err): @@ -615,7 +623,6 @@ def test_td64arr_add_sub_numeric_arr_invalid(self, box, vec, dtype, tdser): err = NullFrequencyError vector = vec.astype(dtype) - # TODO: parametrize over these four ops? with pytest.raises(err): tdser + vector with pytest.raises(err): From 6ccff81f48876fbdf015d98653f2b6367eb79f84 Mon Sep 17 00:00:00 2001 From: Brock Mendel Date: Mon, 12 Nov 2018 12:17:14 -0800 Subject: [PATCH 06/12] isort fixup --- pandas/util/testing.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pandas/util/testing.py b/pandas/util/testing.py index a0901a4c1ee4b..70023c7a706ff 100644 --- a/pandas/util/testing.py +++ b/pandas/util/testing.py @@ -37,7 +37,7 @@ from pandas.core.algorithms import take_1d from pandas.core.arrays import ( DatetimeArrayMixin as DatetimeArray, ExtensionArray, IntervalArray, - PeriodArray, period_array, TimedeltaArrayMixin as TimedeltaArray) + PeriodArray, TimedeltaArrayMixin as TimedeltaArray, period_array) import pandas.core.common as com from pandas.io.common import urlopen From 1ffc21fc705e36292077a4986be8382912b8f551 Mon Sep 17 00:00:00 2001 From: Brock Mendel Date: Mon, 12 Nov 2018 13:08:00 -0800 Subject: [PATCH 07/12] suggested edits --- pandas/core/arrays/timedeltas.py | 5 ++++- pandas/tests/arithmetic/test_timedelta64.py | 14 +++++++------- 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/pandas/core/arrays/timedeltas.py b/pandas/core/arrays/timedeltas.py index dbd706aa945cb..3ecf034879cbf 100644 --- a/pandas/core/arrays/timedeltas.py +++ b/pandas/core/arrays/timedeltas.py @@ -115,8 +115,11 @@ def wrapper(self, other): def _wrap_tdi_op(op): """ Instead of re-implementing multiplication/division etc operations - in the Array class, for now we dispatch to the Timedelta implementations. + in the Array class, for now we dispatch to the TimedeltaIndex + implementations. """ + # TODO: implement directly here and wrap in TimedeltaIndex, instead of + # the other way around def method(self, other): if isinstance(other, (ABCSeries, ABCDataFrame, ABCIndexClass)): return NotImplemented diff --git a/pandas/tests/arithmetic/test_timedelta64.py b/pandas/tests/arithmetic/test_timedelta64.py index 8836551cb967f..73cfbe0ac61c5 100644 --- a/pandas/tests/arithmetic/test_timedelta64.py +++ b/pandas/tests/arithmetic/test_timedelta64.py @@ -467,23 +467,23 @@ def test_td64arr_add_sub_timestamp(self, box): ts = Timestamp('2012-01-01') # TODO: parametrize over types of datetime scalar? - tdser = timedelta_range('1 day', periods=3) + tdarr = timedelta_range('1 day', periods=3) expected = pd.date_range('2012-01-02', periods=3) - tdser = tm.box_expected(tdser, box) + tdarr = tm.box_expected(tdarr, box) expected = tm.box_expected(expected, box) - tm.assert_equal(ts + tdser, expected) - tm.assert_equal(tdser + ts, expected) + tm.assert_equal(ts + tdarr, expected) + tm.assert_equal(tdarr + ts, expected) expected2 = pd.date_range('2011-12-31', periods=3, freq='-1D') expected2 = tm.box_expected(expected2, box) - tm.assert_equal(ts - tdser, expected2) - tm.assert_equal(ts + (-tdser), expected2) + tm.assert_equal(ts - tdarr, expected2) + tm.assert_equal(ts + (-tdarr), expected2) with pytest.raises(TypeError): - tdser - ts + tdarr - ts def test_tdi_sub_dt64_array(self, box_with_timedelta): box = box_with_timedelta From 8c9f296e51cd844d297595e52aa7e84f15a18e6e Mon Sep 17 00:00:00 2001 From: jbrockmendel Date: Mon, 12 Nov 2018 13:57:08 -0800 Subject: [PATCH 08/12] Fixup unused import --- pandas/core/ops.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/pandas/core/ops.py b/pandas/core/ops.py index b14115473354a..fbfdfb9c01237 100644 --- a/pandas/core/ops.py +++ b/pandas/core/ops.py @@ -43,8 +43,7 @@ ABCSeries, ABCDataFrame, ABCPanel, ABCIndex, ABCIndexClass, - ABCSparseSeries, ABCSparseArray, - ABCTimedeltaArray) + ABCSparseSeries, ABCSparseArray) # ----------------------------------------------------------------------------- From 74046baebd2854d9ade317efb89f194546f9ab0e Mon Sep 17 00:00:00 2001 From: Brock Mendel Date: Thu, 15 Nov 2018 09:49:59 -0800 Subject: [PATCH 09/12] implement abs, tests --- pandas/core/arrays/timedeltas.py | 4 +++ pandas/tests/arrays/test_timedeltas.py | 36 +++++++++++++++++++++++++- 2 files changed, 39 insertions(+), 1 deletion(-) diff --git a/pandas/core/arrays/timedeltas.py b/pandas/core/arrays/timedeltas.py index 898f627edc148..2236f66d96aaf 100644 --- a/pandas/core/arrays/timedeltas.py +++ b/pandas/core/arrays/timedeltas.py @@ -344,6 +344,10 @@ def __neg__(self): return type(self)(-self._data, freq=-self.freq) return type(self)(-self._data) + def __abs__(self): + # Note: freq is not preserved + return type(self)(np.abs(self._data)) + # ---------------------------------------------------------------- # Conversion Methods - Vectorized analogues of Timedelta methods diff --git a/pandas/tests/arrays/test_timedeltas.py b/pandas/tests/arrays/test_timedeltas.py index 3ff807daeeab9..5cce82c3f634a 100644 --- a/pandas/tests/arrays/test_timedeltas.py +++ b/pandas/tests/arrays/test_timedeltas.py @@ -1,5 +1,39 @@ # -*- coding: utf-8 -*- +import numpy as np + +import pandas as pd +from pandas.core.arrays import TimedeltaArrayMixin as TimedeltaArray +import pandas.util.testing as tm + class TestTimedeltaArray(object): - pass + + def test_abs(self): + vals = np.array([-3600, 'NaT', 7200], dtype='M8[s]') + arr = TimedeltaArray(vals) + + evals = np.array([3600, 'NaT', 7200], dtype='M8[s]') + expected = TimedeltaArray(evals) + + result = abs(arr) + tm.assert_timedelta_array_equal(result, expected) + + def test_neg(self): + vals = np.array([-3600, 'NaT', 7200], dtype='M8[s]') + arr = TimedeltaArray(vals) + + evals = np.array([3600, 'NaT', -7200], dtype='M8[s]') + expected = TimedeltaArray(evals) + + result = -arr + tm.assert_timedelta_array_equal(result, expected) + + def test_neg_freq(self): + tdi = pd.timedelta_range('2 Days', periods=4, freq='H') + arr = TimedeltaArray(tdi) + + expected = TimedeltaArray(-tdi._data, freq=-dti.freq) + + result = -arr + tm.assert_timedelta_array_equal(result, expected) From 1c9fb1a5096941697f32ce7771831518b7892ca5 Mon Sep 17 00:00:00 2001 From: Brock Mendel Date: Thu, 15 Nov 2018 09:58:41 -0800 Subject: [PATCH 10/12] test fixups --- pandas/tests/arrays/test_timedeltas.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/pandas/tests/arrays/test_timedeltas.py b/pandas/tests/arrays/test_timedeltas.py index 5cce82c3f634a..4d2664054b1c1 100644 --- a/pandas/tests/arrays/test_timedeltas.py +++ b/pandas/tests/arrays/test_timedeltas.py @@ -10,20 +10,20 @@ class TestTimedeltaArray(object): def test_abs(self): - vals = np.array([-3600, 'NaT', 7200], dtype='M8[s]') + vals = np.array([-3600 * 10**9, 'NaT', 7200 * 10**9], dtype='m8[ns]') arr = TimedeltaArray(vals) - evals = np.array([3600, 'NaT', 7200], dtype='M8[s]') + evals = np.array([3600 * 10**9, 'NaT', 7200 * 10**9], dtype='m8[ns]') expected = TimedeltaArray(evals) result = abs(arr) tm.assert_timedelta_array_equal(result, expected) def test_neg(self): - vals = np.array([-3600, 'NaT', 7200], dtype='M8[s]') + vals = np.array([-3600 * 10**9, 'NaT', 7200 * 10**9], dtype='m8[ns]') arr = TimedeltaArray(vals) - evals = np.array([3600, 'NaT', -7200], dtype='M8[s]') + evals = np.array([3600 * 10**9, 'NaT', -7200 * 10**9], dtype='m8[ns]') expected = TimedeltaArray(evals) result = -arr @@ -31,9 +31,9 @@ def test_neg(self): def test_neg_freq(self): tdi = pd.timedelta_range('2 Days', periods=4, freq='H') - arr = TimedeltaArray(tdi) + arr = TimedeltaArray(tdi, freq=tdi.freq) - expected = TimedeltaArray(-tdi._data, freq=-dti.freq) + expected = TimedeltaArray(-tdi._data, freq=-tdi.freq) result = -arr tm.assert_timedelta_array_equal(result, expected) From 9c11a6c774373bd98f0186e3bfba2465d8a6f85e Mon Sep 17 00:00:00 2001 From: Brock Mendel Date: Sun, 18 Nov 2018 07:27:17 -0800 Subject: [PATCH 11/12] use box_with_array instead of box_with_timedelta --- pandas/tests/arithmetic/conftest.py | 9 -- pandas/tests/arithmetic/test_timedelta64.py | 167 +++++++++----------- 2 files changed, 73 insertions(+), 103 deletions(-) diff --git a/pandas/tests/arithmetic/conftest.py b/pandas/tests/arithmetic/conftest.py index 91350225126f3..235a4dea69a49 100644 --- a/pandas/tests/arithmetic/conftest.py +++ b/pandas/tests/arithmetic/conftest.py @@ -208,15 +208,6 @@ def box_with_datetime(request): return request.param -@pytest.fixture(params=[pd.Index, pd.Series, pd.DataFrame, TimedeltaArray], - ids=id_func) -def box_with_timedelta(request): - """ - Like `box`, but specific to timedelta64 for also testing TimedeltaArray - """ - return request.param - - @pytest.fixture(params=[pd.Index, pd.Series, pd.DataFrame, tm.to_array], ids=id_func) def box_with_array(request): diff --git a/pandas/tests/arithmetic/test_timedelta64.py b/pandas/tests/arithmetic/test_timedelta64.py index 73cfbe0ac61c5..651fc4bf96fce 100644 --- a/pandas/tests/arithmetic/test_timedelta64.py +++ b/pandas/tests/arithmetic/test_timedelta64.py @@ -368,12 +368,10 @@ def test_timedelta64_ops_nat(self): # ------------------------------------------------------------- # Invalid Operations - def test_td64arr_add_str_invalid(self, box_with_timedelta): + def test_td64arr_add_str_invalid(self, box_with_array): # GH#13624 - box = box_with_timedelta - tdi = TimedeltaIndex(['1 day', '2 days']) - tdi = tm.box_expected(tdi, box) + tdi = tm.box_expected(tdi, box_with_array) with pytest.raises(TypeError): tdi + 'a' @@ -384,24 +382,20 @@ def test_td64arr_add_str_invalid(self, box_with_timedelta): @pytest.mark.parametrize('op', [operator.add, ops.radd, operator.sub, ops.rsub], ids=lambda x: x.__name__) - def test_td64arr_add_sub_float(self, box_with_timedelta, op, other): - box = box_with_timedelta - + def test_td64arr_add_sub_float(self, box_with_array, op, other): tdi = TimedeltaIndex(['-1 days', '-1 days']) - tdi = tm.box_expected(tdi, box) + tdi = tm.box_expected(tdi, box_with_array) with pytest.raises(TypeError): op(tdi, other) @pytest.mark.parametrize('freq', [None, 'H']) - def test_td64arr_sub_period(self, box_with_timedelta, freq): + def test_td64arr_sub_period(self, box_with_array, freq): # GH#13078 # not supported, check TypeError - box = box_with_timedelta - p = pd.Period('2011-01-01', freq='D') idx = TimedeltaIndex(['1 hours', '2 hours'], freq=freq) - idx = tm.box_expected(idx, box) + idx = tm.box_expected(idx, box_with_array) with pytest.raises(TypeError): idx - p @@ -411,27 +405,23 @@ def test_td64arr_sub_period(self, box_with_timedelta, freq): @pytest.mark.parametrize('pi_freq', ['D', 'W', 'Q', 'H']) @pytest.mark.parametrize('tdi_freq', [None, 'H']) - def test_td64arr_sub_pi(self, box_with_timedelta, tdi_freq, pi_freq): + def test_td64arr_sub_pi(self, box_with_array, tdi_freq, pi_freq): # GH#20049 subtracting PeriodIndex should raise TypeError - box = box_with_timedelta - tdi = TimedeltaIndex(['1 hours', '2 hours'], freq=tdi_freq) dti = Timestamp('2018-03-07 17:16:40') + tdi pi = dti.to_period(pi_freq) # TODO: parametrize over box for pi? - tdi = tm.box_expected(tdi, box) + tdi = tm.box_expected(tdi, box_with_array) with pytest.raises(TypeError): tdi - pi # ------------------------------------------------------------- # Binary operations td64 arraylike and datetime-like - def test_td64arr_sub_timestamp_raises(self, box_with_timedelta): - box = box_with_timedelta - + def test_td64arr_sub_timestamp_raises(self, box_with_array): idx = TimedeltaIndex(['1 day', '2 day']) - idx = tm.box_expected(idx, box) + idx = tm.box_expected(idx, box_with_array) msg = ("cannot subtract a datelike from|" "Could not operate|" @@ -439,9 +429,9 @@ def test_td64arr_sub_timestamp_raises(self, box_with_timedelta): with pytest.raises(TypeError, match=msg): idx - Timestamp('2011-01-01') - def test_td64arr_add_timestamp(self, box_with_timedelta, tz_naive_fixture): + def test_td64arr_add_timestamp(self, box_with_array, tz_naive_fixture): # GH#23215 - box = box_with_timedelta + box = box_with_array xbox = box if box is not TimedeltaArray else DatetimeArray # TODO: parametrize over scalar datetime types? @@ -485,8 +475,8 @@ def test_td64arr_add_sub_timestamp(self, box): with pytest.raises(TypeError): tdarr - ts - def test_tdi_sub_dt64_array(self, box_with_timedelta): - box = box_with_timedelta + def test_tdi_sub_dt64_array(self, box_with_array): + box = box_with_array xbox = box if box is not TimedeltaArray else DatetimeArray dti = pd.date_range('2016-01-01', periods=3) @@ -504,8 +494,8 @@ def test_tdi_sub_dt64_array(self, box_with_timedelta): result = dtarr - tdi tm.assert_equal(result, expected) - def test_tdi_add_dt64_array(self, box_with_timedelta): - box = box_with_timedelta + def test_tdi_add_dt64_array(self, box_with_array): + box = box_with_array xbox = box if box is not TimedeltaArray else DatetimeArray dti = pd.date_range('2016-01-01', periods=3) @@ -521,9 +511,9 @@ def test_tdi_add_dt64_array(self, box_with_timedelta): result = dtarr + tdi tm.assert_equal(result, expected) - def test_td64arr_add_datetime64_nat(self, box_with_timedelta): + def test_td64arr_add_datetime64_nat(self, box_with_array): # GH#23215 - box = box_with_timedelta + box = box_with_array xbox = box if box is not TimedeltaArray else pd.Index other = np.datetime64('NaT') @@ -554,9 +544,9 @@ def test_td64arr_add_int_series_invalid(self, box, tdser): with pytest.raises(err): int_ser - tdser - def test_td64arr_add_intlike(self, box_with_timedelta): + def test_td64arr_add_intlike(self, box_with_array): # GH#19123 - box = box_with_timedelta + box = box_with_array tdi = TimedeltaIndex(['59 days', '59 days', 'NaT']) ser = tm.box_expected(tdi, box) @@ -589,9 +579,9 @@ def test_td64arr_add_intlike(self, box_with_timedelta): ser - pd.Index(other) @pytest.mark.parametrize('scalar', [1, 1.5, np.array(2)]) - def test_td64arr_add_sub_numeric_scalar_invalid(self, box_with_timedelta, + def test_td64arr_add_sub_numeric_scalar_invalid(self, box_with_array, scalar, tdser): - box = box_with_timedelta + box = box_with_array tdser = tm.box_expected(tdser, box) err = TypeError @@ -1041,8 +1031,8 @@ def test_timedelta64_conversions(self, m, unit): # Multiplication # organized with scalar others first, then array-like - def test_td64arr_mul_int(self, box_with_timedelta): - box = box_with_timedelta + def test_td64arr_mul_int(self, box_with_array): + box = box_with_array idx = TimedeltaIndex(np.arange(5, dtype='int64')) idx = tm.box_expected(idx, box) @@ -1054,16 +1044,16 @@ def test_td64arr_mul_int(self, box_with_timedelta): tm.assert_equal(result, idx) def test_td64arr_mul_tdlike_scalar_raises(self, two_hours, - box_with_timedelta): - box = box_with_timedelta + box_with_array): + box = box_with_array rng = timedelta_range('1 days', '10 days', name='foo') rng = tm.box_expected(rng, box) with pytest.raises(TypeError): rng * two_hours - def test_tdi_mul_int_array_zerodim(self, box_with_timedelta): - box = box_with_timedelta + def test_tdi_mul_int_array_zerodim(self, box_with_array): + box = box_with_array rng5 = np.arange(5, dtype='int64') idx = TimedeltaIndex(rng5) @@ -1075,8 +1065,8 @@ def test_tdi_mul_int_array_zerodim(self, box_with_timedelta): result = idx * np.array(5, dtype='int64') tm.assert_equal(result, expected) - def test_tdi_mul_int_array(self, box_with_timedelta): - box = box_with_timedelta + def test_tdi_mul_int_array(self, box_with_array): + box = box_with_array rng5 = np.arange(5, dtype='int64') idx = TimedeltaIndex(rng5) @@ -1088,8 +1078,8 @@ def test_tdi_mul_int_array(self, box_with_timedelta): result = idx * rng5 tm.assert_equal(result, expected) - def test_tdi_mul_int_series(self, box_with_timedelta): - box = box_with_timedelta + def test_tdi_mul_int_series(self, box_with_array): + box = box_with_array xbox = pd.Series if box in [pd.Index, TimedeltaArray] else box idx = TimedeltaIndex(np.arange(5, dtype='int64')) @@ -1101,8 +1091,8 @@ def test_tdi_mul_int_series(self, box_with_timedelta): result = idx * pd.Series(np.arange(5, dtype='int64')) tm.assert_equal(result, expected) - def test_tdi_mul_float_series(self, box_with_timedelta): - box = box_with_timedelta + def test_tdi_mul_float_series(self, box_with_array): + box = box_with_array xbox = pd.Series if box in [pd.Index, TimedeltaArray] else box idx = TimedeltaIndex(np.arange(5, dtype='int64')) @@ -1123,8 +1113,8 @@ def test_tdi_mul_float_series(self, box_with_timedelta): pd.Float64Index(range(1, 11)), pd.RangeIndex(1, 11) ], ids=lambda x: type(x).__name__) - def test_tdi_rmul_arraylike(self, other, box_with_timedelta): - box = box_with_timedelta + def test_tdi_rmul_arraylike(self, other, box_with_array): + box = box_with_array xbox = get_upcast_box(box, other) tdi = TimedeltaIndex(['1 Day'] * 10) @@ -1141,17 +1131,17 @@ def test_tdi_rmul_arraylike(self, other, box_with_timedelta): # ------------------------------------------------------------------ # __div__ - def test_td64arr_div_nat_invalid(self, box_with_timedelta): + def test_td64arr_div_nat_invalid(self, box_with_array): # don't allow division by NaT (maybe could in the future) - box = box_with_timedelta + box = box_with_array rng = timedelta_range('1 days', '10 days', name='foo') rng = tm.box_expected(rng, box) with pytest.raises(TypeError): rng / pd.NaT - def test_td64arr_div_int(self, box_with_timedelta): - box = box_with_timedelta + def test_td64arr_div_int(self, box_with_array): + box = box_with_array idx = TimedeltaIndex(np.arange(5, dtype='int64')) idx = tm.box_expected(idx, box) @@ -1159,9 +1149,9 @@ def test_td64arr_div_int(self, box_with_timedelta): result = idx / 1 tm.assert_equal(result, idx) - def test_tdi_div_tdlike_scalar(self, two_hours, box_with_timedelta): + def test_tdi_div_tdlike_scalar(self, two_hours, box_with_array): # GH#20088, GH#22163 ensure DataFrame returns correct dtype - box = box_with_timedelta + box = box_with_array xbox = box if box is not TimedeltaArray else np.ndarray rng = timedelta_range('1 days', '10 days', name='foo') @@ -1173,9 +1163,8 @@ def test_tdi_div_tdlike_scalar(self, two_hours, box_with_timedelta): result = rng / two_hours tm.assert_equal(result, expected) - def test_tdi_div_tdlike_scalar_with_nat(self, two_hours, - box_with_timedelta): - box = box_with_timedelta + def test_tdi_div_tdlike_scalar_with_nat(self, two_hours, box_with_array): + box = box_with_array xbox = box if box is not TimedeltaArray else np.ndarray rng = TimedeltaIndex(['1 days', pd.NaT, '2 days'], name='foo') @@ -1190,9 +1179,9 @@ def test_tdi_div_tdlike_scalar_with_nat(self, two_hours, # ------------------------------------------------------------------ # __floordiv__, __rfloordiv__ - def test_td64arr_floordiv_tdscalar(self, box_with_timedelta, scalar_td): + def test_td64arr_floordiv_tdscalar(self, box_with_array, scalar_td): # GH#18831 - box = box_with_timedelta + box = box_with_array xbox = box if box is not TimedeltaArray else np.ndarray td1 = Series([timedelta(minutes=5, seconds=3)] * 3) @@ -1206,9 +1195,9 @@ def test_td64arr_floordiv_tdscalar(self, box_with_timedelta, scalar_td): result = td1 // scalar_td tm.assert_equal(result, expected) - def test_td64arr_rfloordiv_tdscalar(self, box_with_timedelta, scalar_td): + def test_td64arr_rfloordiv_tdscalar(self, box_with_array, scalar_td): # GH#18831 - box = box_with_timedelta + box = box_with_array xbox = box if box is not TimedeltaArray else np.ndarray td1 = Series([timedelta(minutes=5, seconds=3)] * 3) @@ -1222,10 +1211,10 @@ def test_td64arr_rfloordiv_tdscalar(self, box_with_timedelta, scalar_td): result = scalar_td // td1 tm.assert_equal(result, expected) - def test_td64arr_rfloordiv_tdscalar_explicit(self, box_with_timedelta, + def test_td64arr_rfloordiv_tdscalar_explicit(self, box_with_array, scalar_td): # GH#18831 - box = box_with_timedelta + box = box_with_array xbox = box if box is not TimedeltaArray else np.ndarray td1 = Series([timedelta(minutes=5, seconds=3)] * 3) @@ -1241,17 +1230,14 @@ def test_td64arr_rfloordiv_tdscalar_explicit(self, box_with_timedelta, result = td1.__rfloordiv__(scalar_td) tm.assert_equal(result, expected) - def test_td64arr_floordiv_int(self, box_with_timedelta): - box = box_with_timedelta - + def test_td64arr_floordiv_int(self, box_with_array): idx = TimedeltaIndex(np.arange(5, dtype='int64')) - idx = tm.box_expected(idx, box) + idx = tm.box_expected(idx, box_with_array) result = idx // 1 tm.assert_equal(result, idx) - def test_td64arr_floordiv_tdlike_scalar(self, two_hours, - box_with_timedelta): - box = box_with_timedelta + def test_td64arr_floordiv_tdlike_scalar(self, two_hours, box_with_array): + box = box_with_array xbox = box if box is not TimedeltaArray else np.ndarray tdi = timedelta_range('1 days', '10 days', name='foo') @@ -1269,10 +1255,9 @@ def test_td64arr_floordiv_tdlike_scalar(self, two_hours, Timedelta('10m7s'), Timedelta('10m7s').to_timedelta64() ], ids=lambda x: type(x).__name__) - def test_td64arr_rfloordiv_tdlike_scalar(self, scalar_td, - box_with_timedelta): + def test_td64arr_rfloordiv_tdlike_scalar(self, scalar_td, box_with_array): # GH#19125 - box = box_with_timedelta + box = box_with_array xbox = box if box is not TimedeltaArray else np.ndarray tdi = TimedeltaIndex(['00:05:03', '00:05:03', pd.NaT], freq=None) @@ -1293,8 +1278,8 @@ def test_td64arr_rfloordiv_tdlike_scalar(self, scalar_td, # ------------------------------------------------------------------ # Operations with invalid others - def test_td64arr_mul_tdscalar_invalid(self, box_with_timedelta, scalar_td): - box = box_with_timedelta + def test_td64arr_mul_tdscalar_invalid(self, box_with_array, scalar_td): + box = box_with_array td1 = Series([timedelta(minutes=5, seconds=3)] * 3) td1.iloc[2] = np.nan @@ -1310,8 +1295,8 @@ def test_td64arr_mul_tdscalar_invalid(self, box_with_timedelta, scalar_td): with pytest.raises(TypeError, match=pattern): scalar_td * td1 - def test_td64arr_mul_too_short_raises(self, box_with_timedelta): - box = box_with_timedelta + def test_td64arr_mul_too_short_raises(self, box_with_array): + box = box_with_array idx = TimedeltaIndex(np.arange(5, dtype='int64')) idx = tm.box_expected(idx, box) @@ -1320,11 +1305,9 @@ def test_td64arr_mul_too_short_raises(self, box_with_timedelta): with pytest.raises(ValueError): idx * np.array([1, 2]) - def test_td64arr_mul_td64arr_raises(self, box_with_timedelta): - box = box_with_timedelta - + def test_td64arr_mul_td64arr_raises(self, box_with_array): idx = TimedeltaIndex(np.arange(5, dtype='int64')) - idx = tm.box_expected(idx, box) + idx = tm.box_expected(idx, box_with_array) with pytest.raises(TypeError): idx * idx @@ -1332,10 +1315,10 @@ def test_td64arr_mul_td64arr_raises(self, box_with_timedelta): # Operations with numeric others @pytest.mark.parametrize('one', [1, np.array(1), 1.0, np.array(1.0)]) - def test_td64arr_mul_numeric_scalar(self, box_with_timedelta, one, tdser): + def test_td64arr_mul_numeric_scalar(self, box_with_array, one, tdser): # GH#4521 # divide/multiply by integers - box = box_with_timedelta + box = box_with_array expected = Series(['-59 Days', '-59 Days', 'NaT'], dtype='timedelta64[ns]') @@ -1358,15 +1341,13 @@ def test_td64arr_mul_numeric_scalar(self, box_with_timedelta, one, tdser): tm.assert_equal(result, expected) @pytest.mark.parametrize('two', [2, 2.0, np.array(2), np.array(2.0)]) - def test_td64arr_div_numeric_scalar(self, box_with_timedelta, two, tdser): + def test_td64arr_div_numeric_scalar(self, box_with_array, two, tdser): # GH#4521 # divide/multiply by integers - box = box_with_timedelta - expected = Series(['29.5D', '29.5D', 'NaT'], dtype='timedelta64[ns]') - tdser = tm.box_expected(tdser, box) - expected = tm.box_expected(expected, box) + tdser = tm.box_expected(tdser, box_with_array) + expected = tm.box_expected(expected, box_with_array) result = tdser / two tm.assert_equal(result, expected) @@ -1379,11 +1360,11 @@ def test_td64arr_div_numeric_scalar(self, box_with_timedelta, two, tdser): Series([20, 30, 40])], ids=lambda x: type(x).__name__) @pytest.mark.parametrize('op', [operator.mul, ops.rmul]) - def test_td64arr_rmul_numeric_array(self, op, box_with_timedelta, + def test_td64arr_rmul_numeric_array(self, op, box_with_array, vector, dtype, tdser): # GH#4521 # divide/multiply by integers - box = box_with_timedelta + box = box_with_array xbox = get_upcast_box(box, vector) vector = vector.astype(dtype) @@ -1404,11 +1385,11 @@ def test_td64arr_rmul_numeric_array(self, op, box_with_timedelta, pd.Index([20, 30, 40]), Series([20, 30, 40])], ids=lambda x: type(x).__name__) - def test_td64arr_div_numeric_array(self, box_with_timedelta, + def test_td64arr_div_numeric_array(self, box_with_array, vector, dtype, tdser): # GH#4521 # divide/multiply by integers - box = box_with_timedelta + box = box_with_array xbox = get_upcast_box(box, vector) vector = vector.astype(dtype) @@ -1480,13 +1461,11 @@ def test_float_series_rdiv_td64arr(self, box, names): class TestTimedeltaArraylikeInvalidArithmeticOps(object): - def test_td64arr_pow_invalid(self, scalar_td, box_with_timedelta): - box = box_with_timedelta - + def test_td64arr_pow_invalid(self, scalar_td, box_with_array): td1 = Series([timedelta(minutes=5, seconds=3)] * 3) td1.iloc[2] = np.nan - td1 = tm.box_expected(td1, box) + td1 = tm.box_expected(td1, box_with_array) # check that we are getting a TypeError # with 'operate' (from core/ops.py) for the ops that are not From e4c7e98e7151deb837de3a0567895a2ec36308f5 Mon Sep 17 00:00:00 2001 From: Brock Mendel Date: Sun, 18 Nov 2018 08:13:12 -0800 Subject: [PATCH 12/12] update fixture usages --- pandas/tests/arithmetic/test_timedelta64.py | 46 +++++++-------------- 1 file changed, 16 insertions(+), 30 deletions(-) diff --git a/pandas/tests/arithmetic/test_timedelta64.py b/pandas/tests/arithmetic/test_timedelta64.py index 651fc4bf96fce..a71b49cbc6d3c 100644 --- a/pandas/tests/arithmetic/test_timedelta64.py +++ b/pandas/tests/arithmetic/test_timedelta64.py @@ -16,9 +16,6 @@ timedelta_range, Timedelta, Timestamp, NaT, Series, TimedeltaIndex, DatetimeIndex, DataFrame) -from pandas.core.arrays import ( - TimedeltaArrayMixin as TimedeltaArray, - DatetimeArrayMixin as DatetimeArray) def get_upcast_box(box, vector): @@ -432,7 +429,6 @@ def test_td64arr_sub_timestamp_raises(self, box_with_array): def test_td64arr_add_timestamp(self, box_with_array, tz_naive_fixture): # GH#23215 box = box_with_array - xbox = box if box is not TimedeltaArray else DatetimeArray # TODO: parametrize over scalar datetime types? tz = tz_naive_fixture @@ -444,7 +440,7 @@ def test_td64arr_add_timestamp(self, box_with_array, tz_naive_fixture): # FIXME: fails with transpose=True because of tz-aware DataFrame # transpose bug idx = tm.box_expected(idx, box, transpose=False) - expected = tm.box_expected(expected, xbox, transpose=False) + expected = tm.box_expected(expected, box, transpose=False) result = idx + other tm.assert_equal(result, expected) @@ -477,7 +473,6 @@ def test_td64arr_add_sub_timestamp(self, box): def test_tdi_sub_dt64_array(self, box_with_array): box = box_with_array - xbox = box if box is not TimedeltaArray else DatetimeArray dti = pd.date_range('2016-01-01', periods=3) tdi = dti - dti.shift(1) @@ -485,7 +480,7 @@ def test_tdi_sub_dt64_array(self, box_with_array): expected = pd.DatetimeIndex(dtarr) - tdi tdi = tm.box_expected(tdi, box) - expected = tm.box_expected(expected, xbox) + expected = tm.box_expected(expected, box) with pytest.raises(TypeError): tdi - dtarr @@ -496,7 +491,6 @@ def test_tdi_sub_dt64_array(self, box_with_array): def test_tdi_add_dt64_array(self, box_with_array): box = box_with_array - xbox = box if box is not TimedeltaArray else DatetimeArray dti = pd.date_range('2016-01-01', periods=3) tdi = dti - dti.shift(1) @@ -504,7 +498,7 @@ def test_tdi_add_dt64_array(self, box_with_array): expected = pd.DatetimeIndex(dtarr) + tdi tdi = tm.box_expected(tdi, box) - expected = tm.box_expected(expected, xbox) + expected = tm.box_expected(expected, box) result = tdi + dtarr tm.assert_equal(result, expected) @@ -514,7 +508,6 @@ def test_tdi_add_dt64_array(self, box_with_array): def test_td64arr_add_datetime64_nat(self, box_with_array): # GH#23215 box = box_with_array - xbox = box if box is not TimedeltaArray else pd.Index other = np.datetime64('NaT') @@ -522,7 +515,7 @@ def test_td64arr_add_datetime64_nat(self, box_with_array): expected = pd.DatetimeIndex(["NaT", "NaT", "NaT"]) tdser = tm.box_expected(tdi, box) - expected = tm.box_expected(expected, xbox) + expected = tm.box_expected(expected, box) tm.assert_equal(tdser + other, expected) tm.assert_equal(other + tdser, expected) @@ -552,7 +545,7 @@ def test_td64arr_add_intlike(self, box_with_array): ser = tm.box_expected(tdi, box) err = TypeError - if box in [pd.Index, TimedeltaArray]: + if box in [pd.Index, tm.to_array]: err = NullFrequencyError other = Series([20, 30, 40], dtype='uint8') @@ -585,7 +578,7 @@ def test_td64arr_add_sub_numeric_scalar_invalid(self, box_with_array, tdser = tm.box_expected(tdser, box) err = TypeError - if box in [pd.Index, TimedeltaArray] and not isinstance(scalar, float): + if box in [pd.Index, tm.to_array] and not isinstance(scalar, float): err = NullFrequencyError with pytest.raises(err): @@ -1080,7 +1073,7 @@ def test_tdi_mul_int_array(self, box_with_array): def test_tdi_mul_int_series(self, box_with_array): box = box_with_array - xbox = pd.Series if box in [pd.Index, TimedeltaArray] else box + xbox = pd.Series if box in [pd.Index, tm.to_array] else box idx = TimedeltaIndex(np.arange(5, dtype='int64')) expected = TimedeltaIndex(np.arange(5, dtype='int64') ** 2) @@ -1093,7 +1086,7 @@ def test_tdi_mul_int_series(self, box_with_array): def test_tdi_mul_float_series(self, box_with_array): box = box_with_array - xbox = pd.Series if box in [pd.Index, TimedeltaArray] else box + xbox = pd.Series if box in [pd.Index, tm.to_array] else box idx = TimedeltaIndex(np.arange(5, dtype='int64')) idx = tm.box_expected(idx, box) @@ -1152,26 +1145,24 @@ def test_td64arr_div_int(self, box_with_array): def test_tdi_div_tdlike_scalar(self, two_hours, box_with_array): # GH#20088, GH#22163 ensure DataFrame returns correct dtype box = box_with_array - xbox = box if box is not TimedeltaArray else np.ndarray rng = timedelta_range('1 days', '10 days', name='foo') expected = pd.Float64Index((np.arange(10) + 1) * 12, name='foo') rng = tm.box_expected(rng, box) - expected = tm.box_expected(expected, xbox) + expected = tm.box_expected(expected, box) result = rng / two_hours tm.assert_equal(result, expected) def test_tdi_div_tdlike_scalar_with_nat(self, two_hours, box_with_array): box = box_with_array - xbox = box if box is not TimedeltaArray else np.ndarray rng = TimedeltaIndex(['1 days', pd.NaT, '2 days'], name='foo') expected = pd.Float64Index([12, np.nan, 24], name='foo') rng = tm.box_expected(rng, box) - expected = tm.box_expected(expected, xbox) + expected = tm.box_expected(expected, box) result = rng / two_hours tm.assert_equal(result, expected) @@ -1182,7 +1173,6 @@ def test_tdi_div_tdlike_scalar_with_nat(self, two_hours, box_with_array): def test_td64arr_floordiv_tdscalar(self, box_with_array, scalar_td): # GH#18831 box = box_with_array - xbox = box if box is not TimedeltaArray else np.ndarray td1 = Series([timedelta(minutes=5, seconds=3)] * 3) td1.iloc[2] = np.nan @@ -1190,7 +1180,7 @@ def test_td64arr_floordiv_tdscalar(self, box_with_array, scalar_td): expected = Series([0, 0, np.nan]) td1 = tm.box_expected(td1, box, transpose=False) - expected = tm.box_expected(expected, xbox, transpose=False) + expected = tm.box_expected(expected, box, transpose=False) result = td1 // scalar_td tm.assert_equal(result, expected) @@ -1198,7 +1188,6 @@ def test_td64arr_floordiv_tdscalar(self, box_with_array, scalar_td): def test_td64arr_rfloordiv_tdscalar(self, box_with_array, scalar_td): # GH#18831 box = box_with_array - xbox = box if box is not TimedeltaArray else np.ndarray td1 = Series([timedelta(minutes=5, seconds=3)] * 3) td1.iloc[2] = np.nan @@ -1206,7 +1195,7 @@ def test_td64arr_rfloordiv_tdscalar(self, box_with_array, scalar_td): expected = Series([1, 1, np.nan]) td1 = tm.box_expected(td1, box, transpose=False) - expected = tm.box_expected(expected, xbox, transpose=False) + expected = tm.box_expected(expected, box, transpose=False) result = scalar_td // td1 tm.assert_equal(result, expected) @@ -1215,7 +1204,6 @@ def test_td64arr_rfloordiv_tdscalar_explicit(self, box_with_array, scalar_td): # GH#18831 box = box_with_array - xbox = box if box is not TimedeltaArray else np.ndarray td1 = Series([timedelta(minutes=5, seconds=3)] * 3) td1.iloc[2] = np.nan @@ -1223,7 +1211,7 @@ def test_td64arr_rfloordiv_tdscalar_explicit(self, box_with_array, expected = Series([1, 1, np.nan]) td1 = tm.box_expected(td1, box, transpose=False) - expected = tm.box_expected(expected, xbox, transpose=False) + expected = tm.box_expected(expected, box, transpose=False) # We can test __rfloordiv__ using this syntax, # see `test_timedelta_rfloordiv` @@ -1238,13 +1226,12 @@ def test_td64arr_floordiv_int(self, box_with_array): def test_td64arr_floordiv_tdlike_scalar(self, two_hours, box_with_array): box = box_with_array - xbox = box if box is not TimedeltaArray else np.ndarray tdi = timedelta_range('1 days', '10 days', name='foo') expected = pd.Int64Index((np.arange(10) + 1) * 12, name='foo') tdi = tm.box_expected(tdi, box) - expected = tm.box_expected(expected, xbox) + expected = tm.box_expected(expected, box) result = tdi // two_hours tm.assert_equal(result, expected) @@ -1258,19 +1245,18 @@ def test_td64arr_floordiv_tdlike_scalar(self, two_hours, box_with_array): def test_td64arr_rfloordiv_tdlike_scalar(self, scalar_td, box_with_array): # GH#19125 box = box_with_array - xbox = box if box is not TimedeltaArray else np.ndarray tdi = TimedeltaIndex(['00:05:03', '00:05:03', pd.NaT], freq=None) expected = pd.Index([2.0, 2.0, np.nan]) tdi = tm.box_expected(tdi, box, transpose=False) - expected = tm.box_expected(expected, xbox, transpose=False) + expected = tm.box_expected(expected, box, transpose=False) res = tdi.__rfloordiv__(scalar_td) tm.assert_equal(res, expected) expected = pd.Index([0.0, 0.0, np.nan]) - expected = tm.box_expected(expected, xbox, transpose=False) + expected = tm.box_expected(expected, box, transpose=False) res = tdi // (scalar_td) tm.assert_equal(res, expected)