diff --git a/pandas/tests/arithmetic/conftest.py b/pandas/tests/arithmetic/conftest.py index 844472b8bcf0d..63df26706b3ec 100644 --- a/pandas/tests/arithmetic/conftest.py +++ b/pandas/tests/arithmetic/conftest.py @@ -30,12 +30,21 @@ def zero(request): @pytest.fixture(params=[pd.Float64Index(np.arange(5, dtype='float64')), pd.Int64Index(np.arange(5, dtype='int64')), - pd.UInt64Index(np.arange(5, dtype='uint64'))], + pd.UInt64Index(np.arange(5, dtype='uint64')), + pd.RangeIndex(5)], ids=lambda x: type(x).__name__) -def idx(request): +def numeric_index(request): return request.param +@pytest.fixture +def td_series(): + """ + Return a Series with dtype='timedelta64[ns]', including a NaT. + """ + return pd.Series(['59 Days', '59 Days', 'NaT'], dtype='timedelta64[ns]') + + @pytest.fixture(params=[pd.Timedelta('5m4s').to_pytimedelta(), pd.Timedelta('5m4s'), pd.Timedelta('5m4s').to_timedelta64()], @@ -47,6 +56,76 @@ def scalar_td(request): return request.param +# ------------------------------------------------------------------ +# DateOffset Fixtures + +_common_mismatch = [pd.offsets.YearBegin(2), + pd.offsets.MonthBegin(1), + pd.offsets.Minute()] + + +@pytest.fixture(params=[pd.Timedelta(minutes=30).to_pytimedelta(), + np.timedelta64(30, 's'), + pd.Timedelta(seconds=30)] + _common_mismatch) +def not_hourly(request): + """ + Several timedelta-like and DateOffset instances that are _not_ + compatible with Hourly frequencies. + """ + return request.param + + +@pytest.fixture(params=[np.timedelta64(4, 'h'), + pd.Timedelta(hours=23).to_pytimedelta(), + pd.Timedelta('23:00:00')] + _common_mismatch) +def not_daily(request): + """ + Several timedelta-like and DateOffset instances that are _not_ + compatible with Daily frequencies. + """ + return request.param + + +@pytest.fixture(params=[np.timedelta64(365, 'D'), + pd.Timedelta(365).to_pytimedelta(), + pd.Timedelta(days=365)] + _common_mismatch) +def mismatched(request): + """ + Several timedelta-like and DateOffset instances that are _not_ + compatible with Monthly or Annual frequencies. + """ + return request.param + + +@pytest.fixture(params=[pd.offsets.Day(3), + pd.Timedelta(days=3).to_pytimedelta(), + np.timedelta64(3, 'D'), + pd.offsets.Hour(72), + pd.Timedelta(minutes=60 * 24 * 3).to_pytimedelta(), + np.timedelta64(72, 'h'), + pd.Timedelta('72:00:00')]) +def three_days(request): + """ + Several timedelta-like and DateOffset objects that each represent + a 3-day timedelta + """ + return request.param + + +@pytest.fixture(params=[pd.offsets.Hour(2), + pd.Timedelta(hours=2), + np.timedelta64(2, 'h'), + pd.offsets.Minute(120), + pd.Timedelta(minutes=120).to_pytimedelta(), + np.timedelta64(120, 'm')]) +def two_hours(request): + """ + Several timedelta-like and DateOffset objects that each represent + a 2-hour timedelta + """ + return request.param + + # ------------------------------------------------------------------ @pytest.fixture(params=[pd.Index, pd.Series, pd.DataFrame], diff --git a/pandas/tests/arithmetic/test_datetime64.py b/pandas/tests/arithmetic/test_datetime64.py index d597ea834f097..b6f72a192f42b 100644 --- a/pandas/tests/arithmetic/test_datetime64.py +++ b/pandas/tests/arithmetic/test_datetime64.py @@ -30,14 +30,6 @@ # ------------------------------------------------------------------ # Fixtures -@pytest.fixture(params=[pd.offsets.Hour(2), timedelta(hours=2), - np.timedelta64(2, 'h'), Timedelta(hours=2)], - ids=str) -def delta(request): - # Several ways of representing two hours - return request.param - - @pytest.fixture( params=[ datetime(2011, 1, 1), @@ -1113,40 +1105,40 @@ def test_dti_add_intarray_no_freq(self, box): # ------------------------------------------------------------- # Binary operations DatetimeIndex and timedelta-like - def test_dti_add_timedeltalike(self, tz_naive_fixture, delta, box): + def test_dti_add_timedeltalike(self, tz_naive_fixture, two_hours, box): # GH#22005, GH#22163 check DataFrame doesn't raise TypeError tz = tz_naive_fixture rng = pd.date_range('2000-01-01', '2000-02-01', tz=tz) rng = tm.box_expected(rng, box) - result = rng + delta + result = rng + two_hours expected = pd.date_range('2000-01-01 02:00', '2000-02-01 02:00', tz=tz) expected = tm.box_expected(expected, box) tm.assert_equal(result, expected) - def test_dti_iadd_timedeltalike(self, tz_naive_fixture, delta): + def test_dti_iadd_timedeltalike(self, tz_naive_fixture, two_hours): tz = tz_naive_fixture rng = pd.date_range('2000-01-01', '2000-02-01', tz=tz) expected = pd.date_range('2000-01-01 02:00', '2000-02-01 02:00', tz=tz) - rng += delta + rng += two_hours tm.assert_index_equal(rng, expected) - def test_dti_sub_timedeltalike(self, tz_naive_fixture, delta): + def test_dti_sub_timedeltalike(self, tz_naive_fixture, two_hours): tz = tz_naive_fixture rng = pd.date_range('2000-01-01', '2000-02-01', tz=tz) expected = pd.date_range('1999-12-31 22:00', '2000-01-31 22:00', tz=tz) - result = rng - delta + result = rng - two_hours tm.assert_index_equal(result, expected) - def test_dti_isub_timedeltalike(self, tz_naive_fixture, delta): + def test_dti_isub_timedeltalike(self, tz_naive_fixture, two_hours): tz = tz_naive_fixture rng = pd.date_range('2000-01-01', '2000-02-01', tz=tz) expected = pd.date_range('1999-12-31 22:00', '2000-01-31 22:00', tz=tz) - rng -= delta + rng -= two_hours tm.assert_index_equal(rng, expected) # ------------------------------------------------------------- @@ -1255,8 +1247,8 @@ def test_dti_isub_tdi(self, tz_naive_fixture): def test_add_datetimelike_and_dti(self, addend): # GH#9631 dti = DatetimeIndex(['2011-01-01', '2011-01-02']) - msg = 'cannot add DatetimeIndex and {0}'.format( - type(addend).__name__) + msg = ('cannot add DatetimeIndex and {typ}' + .format(typ=type(addend).__name__)) with tm.assert_raises_regex(TypeError, msg): dti + addend with tm.assert_raises_regex(TypeError, msg): @@ -1266,8 +1258,8 @@ def test_add_datetimelike_and_dti_tz(self, addend): # GH#9631 dti_tz = DatetimeIndex(['2011-01-01', '2011-01-02']).tz_localize('US/Eastern') - msg = 'cannot add DatetimeIndex and {0}'.format( - type(addend).__name__) + msg = ('cannot add DatetimeIndex and {typ}' + .format(typ=type(addend).__name__)) with tm.assert_raises_regex(TypeError, msg): dti_tz + addend with tm.assert_raises_regex(TypeError, msg): diff --git a/pandas/tests/arithmetic/test_numeric.py b/pandas/tests/arithmetic/test_numeric.py index 9ede1a62aaf2e..dd6fa4c987ebe 100644 --- a/pandas/tests/arithmetic/test_numeric.py +++ b/pandas/tests/arithmetic/test_numeric.py @@ -17,15 +17,6 @@ from pandas import Timedelta, Series, Index, TimedeltaIndex -@pytest.fixture(params=[pd.Float64Index(np.arange(5, dtype='float64')), - pd.UInt64Index(np.arange(5, dtype='uint64')), - pd.Int64Index(np.arange(5, dtype='int64')), - pd.RangeIndex(5)], - ids=lambda x: type(x).__name__) -def idx(request): - return request.param - - # ------------------------------------------------------------------ # Comparisons @@ -42,6 +33,30 @@ def test_operator_series_comparison_zerorank(self): expected = 0.0 > pd.Series([1, 2, 3]) tm.assert_series_equal(result, expected) + def test_df_numeric_cmp_dt64_raises(self): + # GH#8932, GH#22163 + ts = pd.Timestamp.now() + df = pd.DataFrame({'x': range(5)}) + with pytest.raises(TypeError): + df > ts + with pytest.raises(TypeError): + df < ts + with pytest.raises(TypeError): + ts < df + with pytest.raises(TypeError): + ts > df + + assert not (df == ts).any().any() + assert (df != ts).all().all() + + def test_compare_invalid(self): + # GH#8058 + # ops testing + a = pd.Series(np.random.randn(5), name=0) + b = pd.Series(np.random.randn(5)) + b.name = pd.Timestamp('2000-01-01') + tm.assert_series_equal(a / b, 1 / (b / a)) + # ------------------------------------------------------------------ # Numeric dtypes Arithmetic with Timedelta Scalar @@ -164,7 +179,8 @@ def test_numeric_arr_rdiv_tdscalar(self, scalar_td, index, box): class TestDivisionByZero(object): - def test_div_zero(self, zero, idx): + def test_div_zero(self, zero, numeric_index): + idx = numeric_index expected = pd.Index([np.nan, np.inf, np.inf, np.inf, np.inf], dtype=np.float64) result = idx / zero @@ -172,7 +188,8 @@ def test_div_zero(self, zero, idx): ser_compat = Series(idx).astype('i8') / np.array(zero).astype('i8') tm.assert_series_equal(ser_compat, Series(result)) - def test_floordiv_zero(self, zero, idx): + def test_floordiv_zero(self, zero, numeric_index): + idx = numeric_index expected = pd.Index([np.nan, np.inf, np.inf, np.inf, np.inf], dtype=np.float64) @@ -181,7 +198,8 @@ def test_floordiv_zero(self, zero, idx): ser_compat = Series(idx).astype('i8') // np.array(zero).astype('i8') tm.assert_series_equal(ser_compat, Series(result)) - def test_mod_zero(self, zero, idx): + def test_mod_zero(self, zero, numeric_index): + idx = numeric_index expected = pd.Index([np.nan, np.nan, np.nan, np.nan, np.nan], dtype=np.float64) result = idx % zero @@ -189,14 +207,13 @@ def test_mod_zero(self, zero, idx): ser_compat = Series(idx).astype('i8') % np.array(zero).astype('i8') tm.assert_series_equal(ser_compat, Series(result)) - def test_divmod_zero(self, zero, idx): - + def test_divmod_zero(self, zero, numeric_index): exleft = pd.Index([np.nan, np.inf, np.inf, np.inf, np.inf], dtype=np.float64) exright = pd.Index([np.nan, np.nan, np.nan, np.nan, np.nan], dtype=np.float64) - result = divmod(idx, zero) + result = divmod(numeric_index, zero) tm.assert_index_equal(result[0], exleft) tm.assert_index_equal(result[1], exright) @@ -406,28 +423,29 @@ def test_div_equiv_binop(self): result = second / first tm.assert_series_equal(result, expected) - def test_div_int(self, idx): + def test_div_int(self, numeric_index): # truediv under PY3 - result = idx / 1 - expected = idx + result = numeric_index / 1 + expected = numeric_index if PY3: expected = expected.astype('float64') tm.assert_index_equal(result, expected) - result = idx / 2 + result = numeric_index / 2 if PY3: expected = expected.astype('float64') - expected = Index(idx.values / 2) + expected = Index(numeric_index.values / 2) tm.assert_index_equal(result, expected) @pytest.mark.parametrize('op', [operator.mul, ops.rmul, operator.floordiv]) - def test_mul_int_identity(self, op, idx, box): - idx = tm.box_expected(idx, box) + def test_mul_int_identity(self, op, numeric_index, box): + idx = tm.box_expected(numeric_index, box) result = op(idx, 1) tm.assert_equal(result, idx) - def test_mul_int_array(self, idx): + def test_mul_int_array(self, numeric_index): + idx = numeric_index didx = idx * idx result = idx * np.array(5, dtype='int64') @@ -437,58 +455,60 @@ def test_mul_int_array(self, idx): result = idx * np.arange(5, dtype=arr_dtype) tm.assert_index_equal(result, didx) - def test_mul_int_series(self, idx): + def test_mul_int_series(self, numeric_index): + idx = numeric_index didx = idx * idx arr_dtype = 'uint64' if isinstance(idx, pd.UInt64Index) else 'int64' result = idx * Series(np.arange(5, dtype=arr_dtype)) tm.assert_series_equal(result, Series(didx)) - def test_mul_float_series(self, idx): + def test_mul_float_series(self, numeric_index): rng5 = np.arange(5, dtype='float64') - result = idx * Series(rng5 + 0.1) + result = numeric_index * Series(rng5 + 0.1) expected = Series(rng5 * (rng5 + 0.1)) tm.assert_series_equal(result, expected) - def test_mul_index(self, idx): + def test_mul_index(self, numeric_index): # in general not true for RangeIndex - if not isinstance(idx, pd.RangeIndex): - result = idx * idx - tm.assert_index_equal(result, idx ** 2) + if not isinstance(numeric_index, pd.RangeIndex): + result = numeric_index * numeric_index + tm.assert_index_equal(result, numeric_index ** 2) - def test_mul_datelike_raises(self, idx): + def test_mul_datelike_raises(self, numeric_index): with pytest.raises(TypeError): - idx * pd.date_range('20130101', periods=5) + numeric_index * pd.date_range('20130101', periods=5) - def test_mul_size_mismatch_raises(self, idx): + def test_mul_size_mismatch_raises(self, numeric_index): with pytest.raises(ValueError): - idx * idx[0:3] + numeric_index * numeric_index[0:3] with pytest.raises(ValueError): - idx * np.array([1, 2]) + numeric_index * np.array([1, 2]) @pytest.mark.parametrize('op', [operator.pow, ops.rpow]) - def test_pow_float(self, op, idx, box): + def test_pow_float(self, op, numeric_index, box): # test power calculations both ways, GH#14973 - expected = pd.Float64Index(op(idx.values, 2.0)) + expected = pd.Float64Index(op(numeric_index.values, 2.0)) - idx = tm.box_expected(idx, box) + idx = tm.box_expected(numeric_index, box) expected = tm.box_expected(expected, box) result = op(idx, 2.0) tm.assert_equal(result, expected) - def test_modulo(self, idx, box): + def test_modulo(self, numeric_index, box): # GH#9244 - expected = Index(idx.values % 2) + expected = Index(numeric_index.values % 2) - idx = tm.box_expected(idx, box) + idx = tm.box_expected(numeric_index, box) expected = tm.box_expected(expected, box) result = idx % 2 tm.assert_equal(result, expected) - def test_divmod(self, idx): + def test_divmod(self, numeric_index): + idx = numeric_index result = divmod(idx, 2) with np.errstate(all='ignore'): div, mod = divmod(idx.values, 2) @@ -506,7 +526,8 @@ def test_divmod(self, idx): @pytest.mark.xfail(reason='GH#19252 Series has no __rdivmod__', strict=True) - def test_divmod_series(self, idx): + def test_divmod_series(self, numeric_index): + idx = numeric_index other = np.ones(idx.values.shape, dtype=idx.values.dtype) * 2 result = divmod(idx, Series(other)) with np.errstate(all='ignore'): @@ -754,6 +775,51 @@ def check(series, other): check(tser, 5) +class TestUFuncCompat(object): + @pytest.mark.parametrize('holder', [pd.Int64Index, pd.UInt64Index, + pd.Float64Index, pd.Series]) + def test_ufunc_coercions(self, holder): + idx = holder([1, 2, 3, 4, 5], name='x') + box = pd.Series if holder is pd.Series else pd.Index + + result = np.sqrt(idx) + assert result.dtype == 'f8' and isinstance(result, box) + exp = pd.Float64Index(np.sqrt(np.array([1, 2, 3, 4, 5])), name='x') + exp = tm.box_expected(exp, box) + tm.assert_equal(result, exp) + + result = np.divide(idx, 2.) + assert result.dtype == 'f8' and isinstance(result, box) + exp = pd.Float64Index([0.5, 1., 1.5, 2., 2.5], name='x') + exp = tm.box_expected(exp, box) + tm.assert_equal(result, exp) + + # _evaluate_numeric_binop + result = idx + 2. + assert result.dtype == 'f8' and isinstance(result, box) + exp = pd.Float64Index([3., 4., 5., 6., 7.], name='x') + exp = tm.box_expected(exp, box) + tm.assert_equal(result, exp) + + result = idx - 2. + assert result.dtype == 'f8' and isinstance(result, box) + exp = pd.Float64Index([-1., 0., 1., 2., 3.], name='x') + exp = tm.box_expected(exp, box) + tm.assert_equal(result, exp) + + result = idx * 1. + assert result.dtype == 'f8' and isinstance(result, box) + exp = pd.Float64Index([1., 2., 3., 4., 5.], name='x') + exp = tm.box_expected(exp, box) + tm.assert_equal(result, exp) + + result = idx / 2. + assert result.dtype == 'f8' and isinstance(result, box) + exp = pd.Float64Index([0.5, 1., 1.5, 2., 2.5], name='x') + exp = tm.box_expected(exp, box) + tm.assert_equal(result, exp) + + class TestObjectDtypeEquivalence(object): # Tests that arithmetic operations match operations executed elementwise diff --git a/pandas/tests/arithmetic/test_object.py b/pandas/tests/arithmetic/test_object.py index 2c1cc83c09f88..3dfabf471ebb9 100644 --- a/pandas/tests/arithmetic/test_object.py +++ b/pandas/tests/arithmetic/test_object.py @@ -180,3 +180,36 @@ def test_series_with_dtype_radd_timedelta(self, dtype): result = ser + pd.Timedelta('3 days') tm.assert_series_equal(result, expected) + + # TODO: cleanup & parametrize over box + def test_mixed_timezone_series_ops_object(self): + # GH#13043 + s = pd.Series([pd.Timestamp('2015-01-01', tz='US/Eastern'), + pd.Timestamp('2015-01-01', tz='Asia/Tokyo')], + name='xxx') + assert s.dtype == object + + exp = pd.Series([pd.Timestamp('2015-01-02', tz='US/Eastern'), + pd.Timestamp('2015-01-02', tz='Asia/Tokyo')], + name='xxx') + tm.assert_series_equal(s + pd.Timedelta('1 days'), exp) + tm.assert_series_equal(pd.Timedelta('1 days') + s, exp) + + # object series & object series + s2 = pd.Series([pd.Timestamp('2015-01-03', tz='US/Eastern'), + pd.Timestamp('2015-01-05', tz='Asia/Tokyo')], + name='xxx') + assert s2.dtype == object + exp = pd.Series([pd.Timedelta('2 days'), pd.Timedelta('4 days')], + name='xxx') + tm.assert_series_equal(s2 - s, exp) + tm.assert_series_equal(s - s2, -exp) + + s = pd.Series([pd.Timedelta('01:00:00'), pd.Timedelta('02:00:00')], + name='xxx', dtype=object) + assert s.dtype == object + + exp = pd.Series([pd.Timedelta('01:30:00'), pd.Timedelta('02:30:00')], + name='xxx') + tm.assert_series_equal(s + pd.Timedelta('00:30:00'), exp) + tm.assert_series_equal(pd.Timedelta('00:30:00') + s, exp) diff --git a/pandas/tests/arithmetic/test_period.py b/pandas/tests/arithmetic/test_period.py index 92123bf48bb47..800a3d7ddc043 100644 --- a/pandas/tests/arithmetic/test_period.py +++ b/pandas/tests/arithmetic/test_period.py @@ -3,7 +3,6 @@ # behave identically. # Specifically for Period dtype import operator -from datetime import timedelta import numpy as np import pytest @@ -17,80 +16,10 @@ import pandas.core.indexes.period as period from pandas.core import ops from pandas import ( - Period, PeriodIndex, period_range, Timedelta, Series, + Period, PeriodIndex, period_range, Series, NaT, _np_version_under1p10) -# ------------------------------------------------------------------ -# Fixtures - -_common_mismatch = [pd.offsets.YearBegin(2), - pd.offsets.MonthBegin(1), - pd.offsets.Minute()] - - -@pytest.fixture(params=[timedelta(minutes=30), - np.timedelta64(30, 's'), - Timedelta(seconds=30)] + _common_mismatch) -def not_hourly(request): - """ - Several timedelta-like and DateOffset instances that are _not_ - compatible with Hourly frequencies. - """ - return request.param - - -@pytest.fixture(params=[np.timedelta64(4, 'h'), - timedelta(hours=23), - Timedelta('23:00:00')] + _common_mismatch) -def not_daily(request): - """ - Several timedelta-like and DateOffset instances that are _not_ - compatible with Daily frequencies. - """ - return request.param - - -@pytest.fixture(params=[np.timedelta64(365, 'D'), - timedelta(365), - Timedelta(days=365)] + _common_mismatch) -def mismatched(request): - """ - Several timedelta-like and DateOffset instances that are _not_ - compatible with Monthly or Annual frequencies. - """ - return request.param - - -@pytest.fixture(params=[pd.offsets.Day(3), - timedelta(days=3), - np.timedelta64(3, 'D'), - pd.offsets.Hour(72), - timedelta(minutes=60 * 24 * 3), - np.timedelta64(72, 'h'), - Timedelta('72:00:00')]) -def three_days(request): - """ - Several timedelta-like and DateOffset objects that each represent - a 3-day timedelta - """ - return request.param - - -@pytest.fixture(params=[pd.offsets.Hour(2), - timedelta(hours=2), - np.timedelta64(2, 'h'), - pd.offsets.Minute(120), - timedelta(minutes=120), - np.timedelta64(120, 'm')]) -def two_hours(request): - """ - Several timedelta-like and DateOffset objects that each represent - a 2-hour timedelta - """ - return request.param - - # ------------------------------------------------------------------ # Comparisons @@ -375,6 +304,98 @@ def test_cmp_series_period_series_mixed_freq(self): tm.assert_series_equal(base <= ser, exp) +# TODO: Needs cleanup & parametrizing over box +class TestPeriodIndexSeriesComparisons(object): + """ Test PeriodIndex and Period Series Ops consistency """ + + def _check(self, values, func, expected): + idx = pd.PeriodIndex(values) + result = func(idx) + if isinstance(expected, pd.Index): + tm.assert_index_equal(result, expected) + else: + # comp op results in bool + tm.assert_numpy_array_equal(result, expected) + + s = pd.Series(values) + result = func(s) + + exp = pd.Series(expected, name=values.name) + tm.assert_series_equal(result, exp) + + def test_pi_comp_period(self): + idx = PeriodIndex(['2011-01', '2011-02', '2011-03', + '2011-04'], freq='M', name='idx') + + f = lambda x: x == pd.Period('2011-03', freq='M') + exp = np.array([False, False, True, False], dtype=np.bool) + self._check(idx, f, exp) + f = lambda x: pd.Period('2011-03', freq='M') == x + self._check(idx, f, exp) + + f = lambda x: x != pd.Period('2011-03', freq='M') + exp = np.array([True, True, False, True], dtype=np.bool) + self._check(idx, f, exp) + f = lambda x: pd.Period('2011-03', freq='M') != x + self._check(idx, f, exp) + + f = lambda x: pd.Period('2011-03', freq='M') >= x + exp = np.array([True, True, True, False], dtype=np.bool) + self._check(idx, f, exp) + + f = lambda x: x > pd.Period('2011-03', freq='M') + exp = np.array([False, False, False, True], dtype=np.bool) + self._check(idx, f, exp) + + f = lambda x: pd.Period('2011-03', freq='M') >= x + exp = np.array([True, True, True, False], dtype=np.bool) + self._check(idx, f, exp) + + def test_pi_comp_period_nat(self): + idx = PeriodIndex(['2011-01', 'NaT', '2011-03', + '2011-04'], freq='M', name='idx') + + f = lambda x: x == pd.Period('2011-03', freq='M') + exp = np.array([False, False, True, False], dtype=np.bool) + self._check(idx, f, exp) + f = lambda x: pd.Period('2011-03', freq='M') == x + self._check(idx, f, exp) + + f = lambda x: x == NaT + exp = np.array([False, False, False, False], dtype=np.bool) + self._check(idx, f, exp) + f = lambda x: NaT == x + self._check(idx, f, exp) + + f = lambda x: x != pd.Period('2011-03', freq='M') + exp = np.array([True, True, False, True], dtype=np.bool) + self._check(idx, f, exp) + f = lambda x: pd.Period('2011-03', freq='M') != x + self._check(idx, f, exp) + + f = lambda x: x != NaT + exp = np.array([True, True, True, True], dtype=np.bool) + self._check(idx, f, exp) + f = lambda x: NaT != x + self._check(idx, f, exp) + + f = lambda x: pd.Period('2011-03', freq='M') >= x + exp = np.array([True, False, True, False], dtype=np.bool) + self._check(idx, f, exp) + + f = lambda x: x < pd.Period('2011-03', freq='M') + exp = np.array([True, False, False, False], dtype=np.bool) + self._check(idx, f, exp) + + f = lambda x: x > NaT + exp = np.array([False, False, False, False], dtype=np.bool) + self._check(idx, f, exp) + + f = lambda x: NaT >= x + exp = np.array([False, False, False, False], dtype=np.bool) + self._check(idx, f, exp) + + # ------------------------------------------------------------------ # Arithmetic diff --git a/pandas/tests/test_arithmetic.py b/pandas/tests/arithmetic/test_timedelta64.py similarity index 74% rename from pandas/tests/test_arithmetic.py rename to pandas/tests/arithmetic/test_timedelta64.py index def7a8be95fc8..6d218662d5823 100644 --- a/pandas/tests/test_arithmetic.py +++ b/pandas/tests/arithmetic/test_timedelta64.py @@ -3,6 +3,7 @@ # behave identically. from datetime import datetime, timedelta import operator +from distutils.version import LooseVersion import pytest import numpy as np @@ -21,50 +22,12 @@ # ------------------------------------------------------------------ # Fixtures -@pytest.fixture -def tdser(): - """ - Return a Series with dtype='timedelta64[ns]', including a NaT. - """ - return Series(['59 Days', '59 Days', 'NaT'], dtype='timedelta64[ns]') - - -@pytest.fixture(params=[pd.offsets.Hour(2), timedelta(hours=2), - np.timedelta64(2, 'h'), Timedelta(hours=2)], - ids=lambda x: type(x).__name__) -def delta(request): - """ - Several ways of representing two hours - """ - return request.param - - -@pytest.fixture(params=[timedelta(minutes=5, seconds=4), - Timedelta('5m4s'), - Timedelta('5m4s').to_timedelta64()], - ids=lambda x: type(x).__name__) -def scalar_td(request): - """ - Several variants of Timedelta scalars representing 5 minutes and 4 seconds - """ - return request.param - - -@pytest.fixture(params=[pd.Index, Series, pd.DataFrame], - ids=lambda x: x.__name__) -def box(request): - """ - Several array-like containers that should have effectively identical - behavior with respect to arithmetic operations. - """ - return request.param - - -@pytest.fixture(params=[pd.Index, - Series, - pytest.param(pd.DataFrame, - marks=pytest.mark.xfail(strict=True))], - ids=lambda x: x.__name__) +@pytest.fixture(params=[ + pd.Index, + Series, + pytest.param(pd.DataFrame, + marks=pytest.mark.xfail(strict=True)) +], ids=lambda x: x.__name__) def box_df_fail(request): """ Fixture equivalent to `box` fixture but xfailing the DataFrame case. @@ -249,6 +212,310 @@ def test_tdi_add_overflow(self): class TestTimedeltaArraylikeAddSubOps(object): # Tests for timedelta64[ns] __add__, __sub__, __radd__, __rsub__ + # ------------------------------------------------------------------ + # Tests moved from older test_arithmetic files but not yet + # cleaned up and parametrized over `box` + + def test_timedelta_ops_with_missing_values(self): + # setup + tdser1 = pd.to_timedelta(Series(['00:00:01'])) + tdser2 = pd.to_timedelta(Series(['00:00:02'])) + tdnat_ser = pd.to_timedelta(Series([pd.NaT])) + tddf1 = pd.DataFrame(['00:00:01']).apply(pd.to_timedelta) + tddf2 = pd.DataFrame(['00:00:02']).apply(pd.to_timedelta) + tdnat_df = pd.DataFrame([pd.NaT]).apply(pd.to_timedelta) + td_scalar1 = pd.to_timedelta('00:00:01') + td_scalar2 = pd.to_timedelta('00:00:02') + + actual = td_scalar1 + td_scalar1 + assert actual == td_scalar2 + actual = td_scalar2 - td_scalar1 + assert actual == td_scalar1 + + actual = tdser1 + tdser1 + tm.assert_series_equal(actual, tdser2) + actual = tdser2 - tdser1 + tm.assert_series_equal(actual, tdser1) + + actual = tdser1 + td_scalar1 + tm.assert_series_equal(actual, tdser2) + actual = td_scalar1 + tdser1 + tm.assert_series_equal(actual, tdser2) + actual = tdser2 - td_scalar1 + tm.assert_series_equal(actual, tdser1) + actual = -td_scalar1 + tdser2 + tm.assert_series_equal(actual, tdser1) + + actual = tdser1 + pd.NaT + tm.assert_series_equal(actual, tdnat_ser) + actual = pd.NaT + tdser1 + tm.assert_series_equal(actual, tdnat_ser) + actual = tdser1 - pd.NaT + tm.assert_series_equal(actual, tdnat_ser) + actual = -pd.NaT + tdser1 + tm.assert_series_equal(actual, tdnat_ser) + + with pytest.raises(TypeError): + tdser1 + np.nan + with pytest.raises(TypeError): + np.nan + tdser1 + with pytest.raises(TypeError): + tdser1 - np.nan + with pytest.raises(TypeError): + -np.nan + tdser1 + + actual = tdser1 + pd.NaT + tm.assert_series_equal(actual, tdnat_ser) + actual = tdser2 - pd.NaT + tm.assert_series_equal(actual, tdnat_ser) + + actual = tdser1 + tddf1 + tm.assert_frame_equal(actual, tddf2) + actual = tdser2 - tddf1 + tm.assert_frame_equal(actual, tddf1) + actual = tddf1 + tdser1 + tm.assert_frame_equal(actual, tddf2) + actual = tddf2 - tdser1 + tm.assert_frame_equal(actual, tddf1) + + actual = tddf1 + tddf1 + tm.assert_frame_equal(actual, tddf2) + actual = tddf2 - tddf1 + tm.assert_frame_equal(actual, tddf1) + + actual = tddf1 + td_scalar1 + tm.assert_frame_equal(actual, tddf2) + actual = tddf2 - td_scalar1 + tm.assert_frame_equal(actual, tddf1) + + actual = tddf1 + pd.NaT + tm.assert_frame_equal(actual, tdnat_df) + actual = tddf1 - pd.NaT + tm.assert_frame_equal(actual, tdnat_df) + + with pytest.raises(TypeError): + tddf1 + np.nan + with pytest.raises(TypeError): + tddf1 - np.nan + + actual = tddf1 + pd.NaT # NaT is datetime, not timedelta + tm.assert_frame_equal(actual, tdnat_df) + actual = tddf1 - pd.NaT + tm.assert_frame_equal(actual, tdnat_df) + + def test_subtraction_ops(self): + # with datetimes/timedelta and tdi/dti + tdi = TimedeltaIndex(['1 days', pd.NaT, '2 days'], name='foo') + dti = pd.date_range('20130101', periods=3, name='bar') + td = Timedelta('1 days') + dt = Timestamp('20130101') + + pytest.raises(TypeError, lambda: tdi - dt) + pytest.raises(TypeError, lambda: tdi - dti) + pytest.raises(TypeError, lambda: td - dt) + pytest.raises(TypeError, lambda: td - dti) + + result = dt - dti + expected = TimedeltaIndex(['0 days', '-1 days', '-2 days'], name='bar') + tm.assert_index_equal(result, expected) + + result = dti - dt + expected = TimedeltaIndex(['0 days', '1 days', '2 days'], name='bar') + tm.assert_index_equal(result, expected) + + result = tdi - td + expected = TimedeltaIndex(['0 days', pd.NaT, '1 days'], name='foo') + tm.assert_index_equal(result, expected, check_names=False) + + result = td - tdi + expected = TimedeltaIndex(['0 days', pd.NaT, '-1 days'], name='foo') + tm.assert_index_equal(result, expected, check_names=False) + + result = dti - td + expected = DatetimeIndex( + ['20121231', '20130101', '20130102'], name='bar') + tm.assert_index_equal(result, expected, check_names=False) + + result = dt - tdi + expected = DatetimeIndex(['20121231', pd.NaT, '20121230'], name='foo') + tm.assert_index_equal(result, expected) + + def test_subtraction_ops_with_tz(self): + + # check that dt/dti subtraction ops with tz are validated + dti = pd.date_range('20130101', periods=3) + ts = Timestamp('20130101') + dt = ts.to_pydatetime() + dti_tz = pd.date_range('20130101', periods=3).tz_localize('US/Eastern') + ts_tz = Timestamp('20130101').tz_localize('US/Eastern') + ts_tz2 = Timestamp('20130101').tz_localize('CET') + dt_tz = ts_tz.to_pydatetime() + td = Timedelta('1 days') + + def _check(result, expected): + assert result == expected + assert isinstance(result, Timedelta) + + # scalars + result = ts - ts + expected = Timedelta('0 days') + _check(result, expected) + + result = dt_tz - ts_tz + expected = Timedelta('0 days') + _check(result, expected) + + result = ts_tz - dt_tz + expected = Timedelta('0 days') + _check(result, expected) + + # tz mismatches + pytest.raises(TypeError, lambda: dt_tz - ts) + pytest.raises(TypeError, lambda: dt_tz - dt) + pytest.raises(TypeError, lambda: dt_tz - ts_tz2) + pytest.raises(TypeError, lambda: dt - dt_tz) + pytest.raises(TypeError, lambda: ts - dt_tz) + pytest.raises(TypeError, lambda: ts_tz2 - ts) + pytest.raises(TypeError, lambda: ts_tz2 - dt) + pytest.raises(TypeError, lambda: ts_tz - ts_tz2) + + # with dti + pytest.raises(TypeError, lambda: dti - ts_tz) + pytest.raises(TypeError, lambda: dti_tz - ts) + pytest.raises(TypeError, lambda: dti_tz - ts_tz2) + + result = dti_tz - dt_tz + expected = TimedeltaIndex(['0 days', '1 days', '2 days']) + tm.assert_index_equal(result, expected) + + result = dt_tz - dti_tz + expected = TimedeltaIndex(['0 days', '-1 days', '-2 days']) + tm.assert_index_equal(result, expected) + + result = dti_tz - ts_tz + expected = TimedeltaIndex(['0 days', '1 days', '2 days']) + tm.assert_index_equal(result, expected) + + result = ts_tz - dti_tz + expected = TimedeltaIndex(['0 days', '-1 days', '-2 days']) + tm.assert_index_equal(result, expected) + + result = td - td + expected = Timedelta('0 days') + _check(result, expected) + + result = dti_tz - td + expected = DatetimeIndex( + ['20121231', '20130101', '20130102'], tz='US/Eastern') + tm.assert_index_equal(result, expected) + + def test_dti_tdi_numeric_ops(self): + # These are normally union/diff set-like ops + tdi = TimedeltaIndex(['1 days', pd.NaT, '2 days'], name='foo') + dti = pd.date_range('20130101', periods=3, name='bar') + + # TODO(wesm): unused? + # td = Timedelta('1 days') + # dt = Timestamp('20130101') + + result = tdi - tdi + expected = TimedeltaIndex(['0 days', pd.NaT, '0 days'], name='foo') + tm.assert_index_equal(result, expected) + + result = tdi + tdi + expected = TimedeltaIndex(['2 days', pd.NaT, '4 days'], name='foo') + tm.assert_index_equal(result, expected) + + result = dti - tdi # name will be reset + expected = DatetimeIndex(['20121231', pd.NaT, '20130101']) + tm.assert_index_equal(result, expected) + + def test_addition_ops(self): + # with datetimes/timedelta and tdi/dti + tdi = TimedeltaIndex(['1 days', pd.NaT, '2 days'], name='foo') + dti = pd.date_range('20130101', periods=3, name='bar') + td = Timedelta('1 days') + dt = Timestamp('20130101') + + result = tdi + dt + expected = DatetimeIndex(['20130102', pd.NaT, '20130103'], name='foo') + tm.assert_index_equal(result, expected) + + result = dt + tdi + expected = DatetimeIndex(['20130102', pd.NaT, '20130103'], name='foo') + tm.assert_index_equal(result, expected) + + result = td + tdi + expected = TimedeltaIndex(['2 days', pd.NaT, '3 days'], name='foo') + tm.assert_index_equal(result, expected) + + result = tdi + td + expected = TimedeltaIndex(['2 days', pd.NaT, '3 days'], name='foo') + tm.assert_index_equal(result, expected) + + # unequal length + pytest.raises(ValueError, lambda: tdi + dti[0:1]) + pytest.raises(ValueError, lambda: tdi[0:1] + dti) + + result = tdi + dti # name will be reset + expected = DatetimeIndex(['20130102', pd.NaT, '20130105']) + tm.assert_index_equal(result, expected) + + result = dti + tdi # name will be reset + expected = DatetimeIndex(['20130102', pd.NaT, '20130105']) + tm.assert_index_equal(result, expected) + + result = dt + td + expected = Timestamp('20130102') + assert result == expected + + result = td + dt + expected = Timestamp('20130102') + assert result == expected + + def test_ops_ndarray(self): + td = Timedelta('1 day') + + # timedelta, timedelta + other = pd.to_timedelta(['1 day']).values + expected = pd.to_timedelta(['2 days']).values + tm.assert_numpy_array_equal(td + other, expected) + if LooseVersion(np.__version__) >= LooseVersion('1.8'): + tm.assert_numpy_array_equal(other + td, expected) + pytest.raises(TypeError, lambda: td + np.array([1])) + pytest.raises(TypeError, lambda: np.array([1]) + td) + + expected = pd.to_timedelta(['0 days']).values + tm.assert_numpy_array_equal(td - other, expected) + if LooseVersion(np.__version__) >= LooseVersion('1.8'): + tm.assert_numpy_array_equal(-other + td, expected) + pytest.raises(TypeError, lambda: td - np.array([1])) + pytest.raises(TypeError, lambda: np.array([1]) - td) + + expected = pd.to_timedelta(['2 days']).values + tm.assert_numpy_array_equal(td * np.array([2]), expected) + tm.assert_numpy_array_equal(np.array([2]) * td, expected) + pytest.raises(TypeError, lambda: td * other) + pytest.raises(TypeError, lambda: other * td) + + tm.assert_numpy_array_equal(td / other, + np.array([1], dtype=np.float64)) + if LooseVersion(np.__version__) >= LooseVersion('1.8'): + tm.assert_numpy_array_equal(other / td, + np.array([1], dtype=np.float64)) + + # timedelta, datetime + other = pd.to_datetime(['2000-01-01']).values + expected = pd.to_datetime(['2000-01-02']).values + tm.assert_numpy_array_equal(td + other, expected) + if LooseVersion(np.__version__) >= LooseVersion('1.8'): + tm.assert_numpy_array_equal(other + td, expected) + + expected = pd.to_datetime(['1999-12-31']).values + tm.assert_numpy_array_equal(-td + other, expected) + if LooseVersion(np.__version__) >= LooseVersion('1.8'): + tm.assert_numpy_array_equal(other - td, expected) + # TODO: moved from tests.series.test_operators, needs splitting, cleanup, # de-duplication, box-parametrization... def test_operators_timedelta64(self): @@ -442,19 +709,11 @@ def test_td64arr_sub_period(self, box, freq): with pytest.raises(TypeError): p - idx - @pytest.mark.parametrize('box', [ - pd.Index, - Series, - pytest.param(pd.DataFrame, - marks=pytest.mark.xfail(reason="broadcasts along " - "wrong axis", - raises=ValueError, - strict=True)) - ], ids=lambda x: x.__name__) @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_df_broadcast_failure, tdi_freq, pi_freq): # GH#20049 subtracting PeriodIndex should raise TypeError + box = box_df_broadcast_failure tdi = TimedeltaIndex(['1 hours', '2 hours'], freq=tdi_freq) dti = Timestamp('2018-03-07 17:16:40') + tdi pi = dti.to_period(pi_freq) @@ -522,8 +781,8 @@ def test_td64arr_add_sub_timestamp(self, box): with pytest.raises(TypeError): tdser - ts - def test_tdi_sub_dt64_array(self, box_df_fail): - box = box_df_fail # DataFrame tries to broadcast incorrectly + def test_tdi_sub_dt64_array(self, box_df_broadcast_failure): + box = box_df_broadcast_failure dti = pd.date_range('2016-01-01', periods=3) tdi = dti - dti.shift(1) @@ -540,8 +799,8 @@ def test_tdi_sub_dt64_array(self, box_df_fail): result = dtarr - tdi tm.assert_equal(result, expected) - def test_tdi_add_dt64_array(self, box_df_fail): - box = box_df_fail # DataFrame tries to broadcast incorrectly + def test_tdi_add_dt64_array(self, box_df_broadcast_failure): + box = box_df_broadcast_failure dti = pd.date_range('2016-01-01', periods=3) tdi = dti - dti.shift(1) @@ -559,58 +818,41 @@ def test_tdi_add_dt64_array(self, box_df_fail): # ------------------------------------------------------------------ # Operations with int-like others - @pytest.mark.parametrize('box', [ - pd.Index, - Series, - pytest.param(pd.DataFrame, - marks=pytest.mark.xfail(reason="Attempts to broadcast " - "incorrectly", - strict=True, raises=ValueError)) - ], ids=lambda x: x.__name__) - def test_td64arr_add_int_series_invalid(self, box, tdser): - tdser = tm.box_expected(tdser, box) + def test_td64arr_add_int_series_invalid(self, box_df_broadcast_failure, + td_series): + box = box_df_broadcast_failure + tdser = tm.box_expected(td_series, box) err = TypeError if box is not pd.Index else NullFrequencyError with pytest.raises(err): tdser + Series([2, 3, 4]) - def test_td64arr_radd_int_series_invalid(self, box_df_fail, tdser): - box = box_df_fail # Tries to broadcast incorrectly - tdser = tm.box_expected(tdser, box) + def test_td64arr_radd_int_series_invalid(self, box_df_broadcast_failure, + td_series): + box = box_df_broadcast_failure + td_series = tm.box_expected(td_series, box) err = TypeError if box is not pd.Index else NullFrequencyError with pytest.raises(err): - Series([2, 3, 4]) + tdser + Series([2, 3, 4]) + td_series - @pytest.mark.parametrize('box', [ - pd.Index, - Series, - pytest.param(pd.DataFrame, - marks=pytest.mark.xfail(reason="Attempts to broadcast " - "incorrectly", - strict=True, raises=ValueError)) - ], ids=lambda x: x.__name__) - def test_td64arr_sub_int_series_invalid(self, box, tdser): - tdser = tm.box_expected(tdser, box) + def test_td64arr_sub_int_series_invalid(self, box_df_broadcast_failure, + td_series): + box = box_df_broadcast_failure + tdser = tm.box_expected(td_series, box) err = TypeError if box is not pd.Index else NullFrequencyError with pytest.raises(err): tdser - Series([2, 3, 4]) - def test_td64arr_rsub_int_series_invalid(self, box_df_fail, tdser): - box = box_df_fail # Tries to broadcast incorrectly - tdser = tm.box_expected(tdser, box) + def test_td64arr_rsub_int_series_invalid(self, box_df_broadcast_failure, + td_series): + box = box_df_broadcast_failure + td_series = tm.box_expected(td_series, box) err = TypeError if box is not pd.Index else NullFrequencyError with pytest.raises(err): - Series([2, 3, 4]) - tdser + Series([2, 3, 4]) - td_series - @pytest.mark.parametrize('box', [ - pd.Index, - Series, - pytest.param(pd.DataFrame, - marks=pytest.mark.xfail(reason="Attempts to broadcast " - "incorrectly", - strict=True, raises=ValueError)) - ], ids=lambda x: x.__name__) - def test_td64arr_add_intlike(self, box): + def test_td64arr_add_intlike(self, box_df_broadcast_failure): # GH#19123 + box = box_df_broadcast_failure tdi = TimedeltaIndex(['59 days', '59 days', 'NaT']) ser = tm.box_expected(tdi, box) err = TypeError if box is not pd.Index else NullFrequencyError @@ -639,14 +881,15 @@ 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, scalar, + td_series): if box is pd.DataFrame and isinstance(scalar, np.ndarray): # raises ValueError pytest.xfail(reason="reversed ops return incorrect answers " "instead of raising.") - tdser = tm.box_expected(tdser, box) + tdser = tm.box_expected(td_series, box) err = TypeError if box is pd.Index and not isinstance(scalar, float): err = NullFrequencyError @@ -669,10 +912,12 @@ def test_td64arr_add_sub_numeric_scalar_invalid(self, box, scalar, tdser): Series([1, 2, 3]) # TODO: Add DataFrame in here? ], ids=lambda x: type(x).__name__) - def test_td64arr_add_sub_numeric_arr_invalid(self, box_df_fail, vec, - dtype, tdser): - box = box_df_fail # tries to broadcast incorrectly - tdser = tm.box_expected(tdser, box) + def test_td64arr_add_sub_numeric_arr_invalid(self, + box_df_broadcast_failure, + vec, dtype, td_series): + box = box_df_broadcast_failure + td_series = tm.box_expected(td_series, box) + err = TypeError if box is pd.Index and not dtype.startswith('float'): err = NullFrequencyError @@ -680,13 +925,13 @@ def test_td64arr_add_sub_numeric_arr_invalid(self, box_df_fail, vec, vector = vec.astype(dtype) # TODO: parametrize over these four ops? with pytest.raises(err): - tdser + vector + td_series + vector with pytest.raises(err): - vector + tdser + vector + td_series with pytest.raises(err): - tdser - vector + td_series - vector with pytest.raises(err): - vector - tdser + vector - td_series # ------------------------------------------------------------------ # Operations with timedelta-like others @@ -744,8 +989,8 @@ def test_timedelta64_operations_with_timedeltas(self): # roundtrip tm.assert_series_equal(result + td2, td1) - def test_td64arr_add_td64_array(self, box_df_fail): - box = box_df_fail # DataFrame tries to broadcast incorrectly + def test_td64arr_add_td64_array(self, box_df_broadcast_failure): + box = box_df_broadcast_failure dti = pd.date_range('2016-01-01', periods=3) tdi = dti - dti.shift(1) @@ -760,8 +1005,8 @@ def test_td64arr_add_td64_array(self, box_df_fail): result = tdarr + tdi tm.assert_equal(result, expected) - def test_td64arr_sub_td64_array(self, box_df_fail): - box = box_df_fail # DataFrame tries to broadcast incorrectly + def test_td64arr_sub_td64_array(self, box_df_broadcast_failure): + box = box_df_broadcast_failure dti = pd.date_range('2016-01-01', periods=3) tdi = dti - dti.shift(1) @@ -777,21 +1022,13 @@ def test_td64arr_sub_td64_array(self, box_df_fail): tm.assert_equal(result, expected) # TODO: parametrize over [add, sub, radd, rsub]? - @pytest.mark.parametrize('box', [ - pd.Index, - Series, - pytest.param(pd.DataFrame, - marks=pytest.mark.xfail(reason="Tries to broadcast " - "incorrectly leading " - "to alignment error", - strict=True, raises=ValueError)) - ], ids=lambda x: x.__name__) @pytest.mark.parametrize('names', [(None, None, None), ('Egon', 'Venkman', None), ('NCC1701D', 'NCC1701D', 'NCC1701D')]) - def test_td64arr_add_sub_tdi(self, box, names): + def test_td64arr_add_sub_tdi(self, box_df_broadcast_failure, names): # GH#17250 make sure result dtype is correct # GH#19043 make sure names are propagated correctly + box = box_df_broadcast_failure tdi = TimedeltaIndex(['0 days', '1 day'], name=names[0]) ser = Series([Timedelta(hours=3), Timedelta(hours=4)], name=names[1]) expected = Series([Timedelta(hours=3), Timedelta(days=1, hours=4)], @@ -843,7 +1080,7 @@ def test_td64arr_sub_NaT(self, box): res = ser - pd.NaT tm.assert_equal(res, expected) - def test_td64arr_add_timedeltalike(self, delta, box): + def test_td64arr_add_timedeltalike(self, two_hours, box): # only test adding/sub offsets as + is now numeric rng = timedelta_range('1 days', '10 days') expected = timedelta_range('1 days 02:00:00', '10 days 02:00:00', @@ -851,10 +1088,10 @@ def test_td64arr_add_timedeltalike(self, delta, box): rng = tm.box_expected(rng, box) expected = tm.box_expected(expected, box) - result = rng + delta + result = rng + two_hours tm.assert_equal(result, expected) - def test_td64arr_sub_timedeltalike(self, delta, box): + def test_td64arr_sub_timedeltalike(self, two_hours, box): # only test adding/sub offsets as - is now numeric rng = timedelta_range('1 days', '10 days') expected = timedelta_range('0 days 22:00:00', '9 days 22:00:00') @@ -862,7 +1099,7 @@ def test_td64arr_sub_timedeltalike(self, delta, box): rng = tm.box_expected(rng, box) expected = tm.box_expected(expected, box) - result = rng - delta + result = rng - two_hours tm.assert_equal(result, expected) # ------------------------------------------------------------------ @@ -901,19 +1138,12 @@ def test_timedelta64_operations_with_DateOffset(self): td - op(5) op(5) - td - @pytest.mark.parametrize('box', [ - pd.Index, - Series, - pytest.param(pd.DataFrame, - marks=pytest.mark.xfail(reason="Tries to broadcast " - "incorrectly", - strict=True, raises=ValueError)) - ], ids=lambda x: x.__name__) @pytest.mark.parametrize('names', [(None, None, None), ('foo', 'bar', None), ('foo', 'foo', 'foo')]) - def test_td64arr_add_offset_index(self, names, box): + def test_td64arr_add_offset_index(self, names, box_df_broadcast_failure): # GH#18849, GH#19744 + box = box_df_broadcast_failure tdi = TimedeltaIndex(['1 days 00:00:00', '3 days 04:00:00'], name=names[0]) other = pd.Index([pd.offsets.Hour(n=1), pd.offsets.Minute(n=-2)], @@ -934,9 +1164,9 @@ def test_td64arr_add_offset_index(self, names, box): # TODO: combine with test_td64arr_add_offset_index by parametrizing # over second box? - def test_td64arr_add_offset_array(self, box_df_fail): + def test_td64arr_add_offset_array(self, box_df_broadcast_failure): # GH#18849 - box = box_df_fail # tries to broadcast incorrectly + box = box_df_broadcast_failure tdi = TimedeltaIndex(['1 days 00:00:00', '3 days 04:00:00']) other = np.array([pd.offsets.Hour(n=1), pd.offsets.Minute(n=-2)]) @@ -957,9 +1187,9 @@ def test_td64arr_add_offset_array(self, box_df_fail): @pytest.mark.parametrize('names', [(None, None, None), ('foo', 'bar', None), ('foo', 'foo', 'foo')]) - def test_td64arr_sub_offset_index(self, names, box_df_fail): + def test_td64arr_sub_offset_index(self, names, box_df_broadcast_failure): # GH#18824, GH#19744 - box = box_df_fail # tries to broadcast incorrectly + box = box_df_broadcast_failure tdi = TimedeltaIndex(['1 days 00:00:00', '3 days 04:00:00'], name=names[0]) other = pd.Index([pd.offsets.Hour(n=1), pd.offsets.Minute(n=-2)], @@ -975,9 +1205,9 @@ def test_td64arr_sub_offset_index(self, names, box_df_fail): res = tdi - other tm.assert_equal(res, expected) - def test_td64arr_sub_offset_array(self, box_df_fail): + def test_td64arr_sub_offset_array(self, box_df_broadcast_failure): # GH#18824 - box = box_df_fail # tries to broadcast incorrectly + box = box_df_broadcast_failure tdi = TimedeltaIndex(['1 days 00:00:00', '3 days 04:00:00']) other = np.array([pd.offsets.Hour(n=1), pd.offsets.Minute(n=-2)]) @@ -994,9 +1224,9 @@ def test_td64arr_sub_offset_array(self, box_df_fail): @pytest.mark.parametrize('names', [(None, None, None), ('foo', 'bar', None), ('foo', 'foo', 'foo')]) - def test_td64arr_with_offset_series(self, names, box_df_fail): + def test_td64arr_with_offset_series(self, names, box_df_broadcast_failure): # GH#18849 - box = box_df_fail # tries to broadcast incorrectly + box = box_df_broadcast_failure box2 = Series if box is pd.Index else box tdi = TimedeltaIndex(['1 days 00:00:00', '3 days 04:00:00'], @@ -1027,9 +1257,10 @@ def test_td64arr_with_offset_series(self, names, box_df_fail): tm.assert_equal(res3, expected_sub) @pytest.mark.parametrize('obox', [np.array, pd.Index, pd.Series]) - def test_td64arr_addsub_anchored_offset_arraylike(self, obox, box_df_fail): + def test_td64arr_addsub_anchored_offset_arraylike( + self, obox, box_df_broadcast_failure): # GH#18824 - box = box_df_fail # DataFrame tries to broadcast incorrectly + box = box_df_broadcast_failure tdi = TimedeltaIndex(['1 days 00:00:00', '3 days 04:00:00']) tdi = tm.box_expected(tdi, box) @@ -1090,11 +1321,11 @@ def test_td64arr_mul_int(self, box): result = 1 * idx tm.assert_equal(result, idx) - def test_td64arr_mul_tdlike_scalar_raises(self, delta, box): + def test_td64arr_mul_tdlike_scalar_raises(self, two_hours, box): rng = timedelta_range('1 days', '10 days', name='foo') rng = tm.box_expected(rng, box) with pytest.raises(TypeError): - rng * delta + rng * two_hours def test_tdi_mul_int_array_zerodim(self, box): rng5 = np.arange(5, dtype='int64') @@ -1107,8 +1338,8 @@ 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_df_fail): - box = box_df_fail # DataFrame tries to broadcast incorrectly + def test_tdi_mul_int_array(self, box_df_broadcast_failure): + box = box_df_broadcast_failure rng5 = np.arange(5, dtype='int64') idx = TimedeltaIndex(rng5) expected = TimedeltaIndex(rng5 ** 2) @@ -1120,7 +1351,7 @@ def test_tdi_mul_int_array(self, box_df_fail): tm.assert_equal(result, expected) def test_tdi_mul_int_series(self, box_df_fail): - box = box_df_fail # DataFrame tries to broadcast incorrectly + box = box_df_fail idx = TimedeltaIndex(np.arange(5, dtype='int64')) expected = TimedeltaIndex(np.arange(5, dtype='int64') ** 2) @@ -1133,7 +1364,7 @@ def test_tdi_mul_int_series(self, box_df_fail): tm.assert_equal(result, expected) def test_tdi_mul_float_series(self, box_df_fail): - box = box_df_fail # DataFrame tries to broadcast incorrectly + box = box_df_fail idx = TimedeltaIndex(np.arange(5, dtype='int64')) idx = tm.box_expected(idx, box) @@ -1186,7 +1417,7 @@ def test_td64arr_div_int(self, box): result = idx / 1 tm.assert_equal(result, idx) - def test_tdi_div_tdlike_scalar(self, delta, box): + def test_tdi_div_tdlike_scalar(self, two_hours, box): # GH#20088, GH#22163 ensure DataFrame returns correct dtype rng = timedelta_range('1 days', '10 days', name='foo') expected = pd.Float64Index((np.arange(10) + 1) * 12, name='foo') @@ -1194,17 +1425,17 @@ def test_tdi_div_tdlike_scalar(self, delta, box): rng = tm.box_expected(rng, box) expected = tm.box_expected(expected, box) - result = rng / delta + result = rng / two_hours tm.assert_equal(result, expected) - def test_tdi_div_tdlike_scalar_with_nat(self, delta, box): + def test_tdi_div_tdlike_scalar_with_nat(self, two_hours, box): 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) - result = rng / delta + result = rng / two_hours tm.assert_equal(result, expected) # ------------------------------------------------------------------ @@ -1260,14 +1491,14 @@ def test_td64arr_floordiv_int(self, box): result = idx // 1 tm.assert_equal(result, idx) - def test_td64arr_floordiv_tdlike_scalar(self, delta, box): + def test_td64arr_floordiv_tdlike_scalar(self, two_hours, box): 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) - result = tdi // delta + result = tdi // two_hours tm.assert_equal(result, expected) # TODO: Is this redundant with test_td64arr_floordiv_tdlike_scalar? @@ -1329,13 +1560,13 @@ 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, one, td_series): # GH#4521 # divide/multiply by integers expected = Series(['-59 Days', '-59 Days', 'NaT'], dtype='timedelta64[ns]') - tdser = tm.box_expected(tdser, box) + tdser = tm.box_expected(td_series, box) expected = tm.box_expected(expected, box) result = tdser * (-one) @@ -1353,12 +1584,12 @@ 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, two, td_series): # GH#4521 # divide/multiply by integers expected = Series(['29.5D', '29.5D', 'NaT'], dtype='timedelta64[ns]') - tdser = tm.box_expected(tdser, box) + tdser = tm.box_expected(td_series, box) expected = tm.box_expected(expected, box) result = tdser / two @@ -1380,7 +1611,8 @@ 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, vector, dtype, tdser): + def test_td64arr_rmul_numeric_array(self, op, box, vector, dtype, + td_series): # GH#4521 # divide/multiply by integers vector = vector.astype(dtype) @@ -1388,7 +1620,7 @@ def test_td64arr_rmul_numeric_array(self, op, box, vector, dtype, tdser): expected = Series(['1180 Days', '1770 Days', 'NaT'], dtype='timedelta64[ns]') - tdser = tm.box_expected(tdser, box) + tdser = tm.box_expected(td_series, 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) @@ -1411,14 +1643,14 @@ def test_td64arr_rmul_numeric_array(self, op, box, vector, dtype, tdser): 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, vector, dtype, td_series): # GH#4521 # divide/multiply by integers vector = vector.astype(dtype) expected = Series(['2.95D', '1D 23H 12m', 'NaT'], dtype='timedelta64[ns]') - tdser = tm.box_expected(tdser, box) + tdser = tm.box_expected(td_series, box) box = Series if (box is pd.Index and type(vector) is Series) else box expected = tm.box_expected(expected, box) @@ -1489,6 +1721,45 @@ def test_float_series_rdiv_td64arr(self, box, names): tm.assert_equal(result, expected) +class TestUFuncCompat(object): + def test_ufunc_coercions(self): + # normal ops are also tested in tseries/test_timedeltas.py + idx = TimedeltaIndex(['2H', '4H', '6H', '8H', '10H'], + freq='2H', name='x') + + for result in [idx * 2, np.multiply(idx, 2)]: + assert isinstance(result, TimedeltaIndex) + exp = TimedeltaIndex(['4H', '8H', '12H', '16H', '20H'], + freq='4H', name='x') + tm.assert_index_equal(result, exp) + assert result.freq == '4H' + + for result in [idx / 2, np.divide(idx, 2)]: + assert isinstance(result, TimedeltaIndex) + exp = TimedeltaIndex(['1H', '2H', '3H', '4H', '5H'], + freq='H', name='x') + tm.assert_index_equal(result, exp) + assert result.freq == 'H' + + idx = TimedeltaIndex(['2H', '4H', '6H', '8H', '10H'], + freq='2H', name='x') + for result in [-idx, np.negative(idx)]: + assert isinstance(result, TimedeltaIndex) + exp = TimedeltaIndex(['-2H', '-4H', '-6H', '-8H', '-10H'], + freq='-2H', name='x') + tm.assert_index_equal(result, exp) + assert result.freq == '-2H' + + idx = TimedeltaIndex(['-2H', '-1H', '0H', '1H', '2H'], + freq='H', name='x') + for result in [abs(idx), np.absolute(idx)]: + assert isinstance(result, TimedeltaIndex) + exp = TimedeltaIndex(['2H', '1H', '0H', '1H', '2H'], + freq=None, name='x') + tm.assert_index_equal(result, exp) + assert result.freq is None + + class TestTimedeltaArraylikeInvalidArithmeticOps(object): @pytest.mark.parametrize('scalar_td', [ diff --git a/pandas/tests/frame/test_arithmetic.py b/pandas/tests/frame/test_arithmetic.py index f142f770a0c54..a6f4e0e38ec5d 100644 --- a/pandas/tests/frame/test_arithmetic.py +++ b/pandas/tests/frame/test_arithmetic.py @@ -48,22 +48,6 @@ def test_mixed_comparison(self): result = df != other assert result.all().all() - def test_df_numeric_cmp_dt64_raises(self): - # GH#8932, GH#22163 - ts = pd.Timestamp.now() - df = pd.DataFrame({'x': range(5)}) - with pytest.raises(TypeError): - df > ts - with pytest.raises(TypeError): - df < ts - with pytest.raises(TypeError): - ts < df - with pytest.raises(TypeError): - ts > df - - assert not (df == ts).any().any() - assert (df != ts).all().all() - def test_df_boolean_comparison_error(self): # GH#4576 # boolean comparisons with a tuple/list give unexpected results diff --git a/pandas/tests/indexes/period/test_ops.py b/pandas/tests/indexes/period/test_ops.py index 85aa3f6a38fb3..5454e682b9afa 100644 --- a/pandas/tests/indexes/period/test_ops.py +++ b/pandas/tests/indexes/period/test_ops.py @@ -412,94 +412,3 @@ def test_freq_setter_deprecated(self): # warning for setter with tm.assert_produces_warning(FutureWarning): idx.freq = pd.offsets.Day() - - -class TestPeriodIndexSeriesMethods(object): - """ Test PeriodIndex and Period Series Ops consistency """ - - def _check(self, values, func, expected): - idx = pd.PeriodIndex(values) - result = func(idx) - if isinstance(expected, pd.Index): - tm.assert_index_equal(result, expected) - else: - # comp op results in bool - tm.assert_numpy_array_equal(result, expected) - - s = pd.Series(values) - result = func(s) - - exp = pd.Series(expected, name=values.name) - tm.assert_series_equal(result, exp) - - def test_pi_comp_period(self): - idx = PeriodIndex(['2011-01', '2011-02', '2011-03', - '2011-04'], freq='M', name='idx') - - f = lambda x: x == pd.Period('2011-03', freq='M') - exp = np.array([False, False, True, False], dtype=np.bool) - self._check(idx, f, exp) - f = lambda x: pd.Period('2011-03', freq='M') == x - self._check(idx, f, exp) - - f = lambda x: x != pd.Period('2011-03', freq='M') - exp = np.array([True, True, False, True], dtype=np.bool) - self._check(idx, f, exp) - f = lambda x: pd.Period('2011-03', freq='M') != x - self._check(idx, f, exp) - - f = lambda x: pd.Period('2011-03', freq='M') >= x - exp = np.array([True, True, True, False], dtype=np.bool) - self._check(idx, f, exp) - - f = lambda x: x > pd.Period('2011-03', freq='M') - exp = np.array([False, False, False, True], dtype=np.bool) - self._check(idx, f, exp) - - f = lambda x: pd.Period('2011-03', freq='M') >= x - exp = np.array([True, True, True, False], dtype=np.bool) - self._check(idx, f, exp) - - def test_pi_comp_period_nat(self): - idx = PeriodIndex(['2011-01', 'NaT', '2011-03', - '2011-04'], freq='M', name='idx') - - f = lambda x: x == pd.Period('2011-03', freq='M') - exp = np.array([False, False, True, False], dtype=np.bool) - self._check(idx, f, exp) - f = lambda x: pd.Period('2011-03', freq='M') == x - self._check(idx, f, exp) - - f = lambda x: x == tslib.NaT - exp = np.array([False, False, False, False], dtype=np.bool) - self._check(idx, f, exp) - f = lambda x: tslib.NaT == x - self._check(idx, f, exp) - - f = lambda x: x != pd.Period('2011-03', freq='M') - exp = np.array([True, True, False, True], dtype=np.bool) - self._check(idx, f, exp) - f = lambda x: pd.Period('2011-03', freq='M') != x - self._check(idx, f, exp) - - f = lambda x: x != tslib.NaT - exp = np.array([True, True, True, True], dtype=np.bool) - self._check(idx, f, exp) - f = lambda x: tslib.NaT != x - self._check(idx, f, exp) - - f = lambda x: pd.Period('2011-03', freq='M') >= x - exp = np.array([True, False, True, False], dtype=np.bool) - self._check(idx, f, exp) - - f = lambda x: x < pd.Period('2011-03', freq='M') - exp = np.array([True, False, False, False], dtype=np.bool) - self._check(idx, f, exp) - - f = lambda x: x > tslib.NaT - exp = np.array([False, False, False, False], dtype=np.bool) - self._check(idx, f, exp) - - f = lambda x: tslib.NaT >= x - exp = np.array([False, False, False, False], dtype=np.bool) - self._check(idx, f, exp) diff --git a/pandas/tests/indexes/test_numeric.py b/pandas/tests/indexes/test_numeric.py index c8aa7f8fd50fd..1cb2cd46a65db 100644 --- a/pandas/tests/indexes/test_numeric.py +++ b/pandas/tests/indexes/test_numeric.py @@ -565,40 +565,6 @@ def test_slice_keep_name(self): idx = self._holder([1, 2], name='asdf') assert idx.name == idx[1:].name - def test_ufunc_coercions(self): - idx = self._holder([1, 2, 3, 4, 5], name='x') - - result = np.sqrt(idx) - assert isinstance(result, Float64Index) - exp = Float64Index(np.sqrt(np.array([1, 2, 3, 4, 5])), name='x') - tm.assert_index_equal(result, exp) - - result = np.divide(idx, 2.) - assert isinstance(result, Float64Index) - exp = Float64Index([0.5, 1., 1.5, 2., 2.5], name='x') - tm.assert_index_equal(result, exp) - - # _evaluate_numeric_binop - result = idx + 2. - assert isinstance(result, Float64Index) - exp = Float64Index([3., 4., 5., 6., 7.], name='x') - tm.assert_index_equal(result, exp) - - result = idx - 2. - assert isinstance(result, Float64Index) - exp = Float64Index([-1., 0., 1., 2., 3.], name='x') - tm.assert_index_equal(result, exp) - - result = idx * 1. - assert isinstance(result, Float64Index) - exp = Float64Index([1., 2., 3., 4., 5.], name='x') - tm.assert_index_equal(result, exp) - - result = idx / 2. - assert isinstance(result, Float64Index) - exp = Float64Index([0.5, 1., 1.5, 2., 2.5], name='x') - tm.assert_index_equal(result, exp) - class TestInt64Index(NumericInt): _dtype = 'int64' diff --git a/pandas/tests/indexes/timedeltas/test_arithmetic.py b/pandas/tests/indexes/timedeltas/test_arithmetic.py index f3bc523ca525e..0ac6ad85dbdf0 100644 --- a/pandas/tests/indexes/timedeltas/test_arithmetic.py +++ b/pandas/tests/indexes/timedeltas/test_arithmetic.py @@ -3,14 +3,13 @@ import pytest import numpy as np from datetime import timedelta -from distutils.version import LooseVersion import pandas as pd import pandas.util.testing as tm from pandas import (DatetimeIndex, TimedeltaIndex, Int64Index, timedelta_range, date_range, Series, - Timestamp, Timedelta) + Timedelta) from pandas.errors import NullFrequencyError @@ -84,45 +83,6 @@ def test_shift_no_freq(self): with pytest.raises(NullFrequencyError): tdi.shift(2) - # ------------------------------------------------------------- - - def test_ufunc_coercions(self): - # normal ops are also tested in tseries/test_timedeltas.py - idx = TimedeltaIndex(['2H', '4H', '6H', '8H', '10H'], - freq='2H', name='x') - - for result in [idx * 2, np.multiply(idx, 2)]: - assert isinstance(result, TimedeltaIndex) - exp = TimedeltaIndex(['4H', '8H', '12H', '16H', '20H'], - freq='4H', name='x') - tm.assert_index_equal(result, exp) - assert result.freq == '4H' - - for result in [idx / 2, np.divide(idx, 2)]: - assert isinstance(result, TimedeltaIndex) - exp = TimedeltaIndex(['1H', '2H', '3H', '4H', '5H'], - freq='H', name='x') - tm.assert_index_equal(result, exp) - assert result.freq == 'H' - - idx = TimedeltaIndex(['2H', '4H', '6H', '8H', '10H'], - freq='2H', name='x') - for result in [-idx, np.negative(idx)]: - assert isinstance(result, TimedeltaIndex) - exp = TimedeltaIndex(['-2H', '-4H', '-6H', '-8H', '-10H'], - freq='-2H', name='x') - tm.assert_index_equal(result, exp) - assert result.freq == '-2H' - - idx = TimedeltaIndex(['-2H', '-1H', '0H', '1H', '2H'], - freq='H', name='x') - for result in [abs(idx), np.absolute(idx)]: - assert isinstance(result, TimedeltaIndex) - exp = TimedeltaIndex(['2H', '1H', '0H', '1H', '2H'], - freq=None, name='x') - tm.assert_index_equal(result, exp) - assert result.freq is None - # ------------------------------------------------------------- # Binary operations TimedeltaIndex and integer @@ -211,159 +171,9 @@ def test_tdi_isub_timedeltalike(self, delta): # ------------------------------------------------------------- - def test_subtraction_ops(self): - # with datetimes/timedelta and tdi/dti - tdi = TimedeltaIndex(['1 days', pd.NaT, '2 days'], name='foo') - dti = date_range('20130101', periods=3, name='bar') - td = Timedelta('1 days') - dt = Timestamp('20130101') - - pytest.raises(TypeError, lambda: tdi - dt) - pytest.raises(TypeError, lambda: tdi - dti) - pytest.raises(TypeError, lambda: td - dt) - pytest.raises(TypeError, lambda: td - dti) - - result = dt - dti - expected = TimedeltaIndex(['0 days', '-1 days', '-2 days'], name='bar') - tm.assert_index_equal(result, expected) - - result = dti - dt - expected = TimedeltaIndex(['0 days', '1 days', '2 days'], name='bar') - tm.assert_index_equal(result, expected) - - result = tdi - td - expected = TimedeltaIndex(['0 days', pd.NaT, '1 days'], name='foo') - tm.assert_index_equal(result, expected, check_names=False) - - result = td - tdi - expected = TimedeltaIndex(['0 days', pd.NaT, '-1 days'], name='foo') - tm.assert_index_equal(result, expected, check_names=False) - - result = dti - td - expected = DatetimeIndex( - ['20121231', '20130101', '20130102'], name='bar') - tm.assert_index_equal(result, expected, check_names=False) - - result = dt - tdi - expected = DatetimeIndex(['20121231', pd.NaT, '20121230'], name='foo') - tm.assert_index_equal(result, expected) - - def test_subtraction_ops_with_tz(self): - - # check that dt/dti subtraction ops with tz are validated - dti = date_range('20130101', periods=3) - ts = Timestamp('20130101') - dt = ts.to_pydatetime() - dti_tz = date_range('20130101', periods=3).tz_localize('US/Eastern') - ts_tz = Timestamp('20130101').tz_localize('US/Eastern') - ts_tz2 = Timestamp('20130101').tz_localize('CET') - dt_tz = ts_tz.to_pydatetime() - td = Timedelta('1 days') - - def _check(result, expected): - assert result == expected - assert isinstance(result, Timedelta) - - # scalars - result = ts - ts - expected = Timedelta('0 days') - _check(result, expected) - - result = dt_tz - ts_tz - expected = Timedelta('0 days') - _check(result, expected) - - result = ts_tz - dt_tz - expected = Timedelta('0 days') - _check(result, expected) - - # tz mismatches - pytest.raises(TypeError, lambda: dt_tz - ts) - pytest.raises(TypeError, lambda: dt_tz - dt) - pytest.raises(TypeError, lambda: dt_tz - ts_tz2) - pytest.raises(TypeError, lambda: dt - dt_tz) - pytest.raises(TypeError, lambda: ts - dt_tz) - pytest.raises(TypeError, lambda: ts_tz2 - ts) - pytest.raises(TypeError, lambda: ts_tz2 - dt) - pytest.raises(TypeError, lambda: ts_tz - ts_tz2) - - # with dti - pytest.raises(TypeError, lambda: dti - ts_tz) - pytest.raises(TypeError, lambda: dti_tz - ts) - pytest.raises(TypeError, lambda: dti_tz - ts_tz2) - - result = dti_tz - dt_tz - expected = TimedeltaIndex(['0 days', '1 days', '2 days']) - tm.assert_index_equal(result, expected) - - result = dt_tz - dti_tz - expected = TimedeltaIndex(['0 days', '-1 days', '-2 days']) - tm.assert_index_equal(result, expected) - - result = dti_tz - ts_tz - expected = TimedeltaIndex(['0 days', '1 days', '2 days']) - tm.assert_index_equal(result, expected) - - result = ts_tz - dti_tz - expected = TimedeltaIndex(['0 days', '-1 days', '-2 days']) - tm.assert_index_equal(result, expected) - - result = td - td - expected = Timedelta('0 days') - _check(result, expected) - - result = dti_tz - td - expected = DatetimeIndex( - ['20121231', '20130101', '20130102'], tz='US/Eastern') - tm.assert_index_equal(result, expected) - - def test_dti_tdi_numeric_ops(self): - # These are normally union/diff set-like ops - tdi = TimedeltaIndex(['1 days', pd.NaT, '2 days'], name='foo') - dti = date_range('20130101', periods=3, name='bar') - - # TODO(wesm): unused? - # td = Timedelta('1 days') - # dt = Timestamp('20130101') - - result = tdi - tdi - expected = TimedeltaIndex(['0 days', pd.NaT, '0 days'], name='foo') - tm.assert_index_equal(result, expected) - - result = tdi + tdi - expected = TimedeltaIndex(['2 days', pd.NaT, '4 days'], name='foo') - tm.assert_index_equal(result, expected) - - result = dti - tdi # name will be reset - expected = DatetimeIndex(['20121231', pd.NaT, '20130101']) - tm.assert_index_equal(result, expected) - def test_addition_ops(self): # with datetimes/timedelta and tdi/dti tdi = TimedeltaIndex(['1 days', pd.NaT, '2 days'], name='foo') - dti = date_range('20130101', periods=3, name='bar') - td = Timedelta('1 days') - dt = Timestamp('20130101') - - result = tdi + dt - expected = DatetimeIndex(['20130102', pd.NaT, '20130103'], name='foo') - tm.assert_index_equal(result, expected) - - result = dt + tdi - expected = DatetimeIndex(['20130102', pd.NaT, '20130103'], name='foo') - tm.assert_index_equal(result, expected) - - result = td + tdi - expected = TimedeltaIndex(['2 days', pd.NaT, '3 days'], name='foo') - tm.assert_index_equal(result, expected) - - result = tdi + td - expected = TimedeltaIndex(['2 days', pd.NaT, '3 days'], name='foo') - tm.assert_index_equal(result, expected) - - # unequal length - pytest.raises(ValueError, lambda: tdi + dti[0:1]) - pytest.raises(ValueError, lambda: tdi[0:1] + dti) # random indexes pytest.raises(NullFrequencyError, lambda: tdi + Int64Index([1, 2, 3])) @@ -371,185 +181,6 @@ def test_addition_ops(self): # this is a union! # pytest.raises(TypeError, lambda : Int64Index([1,2,3]) + tdi) - result = tdi + dti # name will be reset - expected = DatetimeIndex(['20130102', pd.NaT, '20130105']) - tm.assert_index_equal(result, expected) - - result = dti + tdi # name will be reset - expected = DatetimeIndex(['20130102', pd.NaT, '20130105']) - tm.assert_index_equal(result, expected) - - result = dt + td - expected = Timestamp('20130102') - assert result == expected - - result = td + dt - expected = Timestamp('20130102') - assert result == expected - - def test_ops_ndarray(self): - td = Timedelta('1 day') - - # timedelta, timedelta - other = pd.to_timedelta(['1 day']).values - expected = pd.to_timedelta(['2 days']).values - tm.assert_numpy_array_equal(td + other, expected) - if LooseVersion(np.__version__) >= LooseVersion('1.8'): - tm.assert_numpy_array_equal(other + td, expected) - pytest.raises(TypeError, lambda: td + np.array([1])) - pytest.raises(TypeError, lambda: np.array([1]) + td) - - expected = pd.to_timedelta(['0 days']).values - tm.assert_numpy_array_equal(td - other, expected) - if LooseVersion(np.__version__) >= LooseVersion('1.8'): - tm.assert_numpy_array_equal(-other + td, expected) - pytest.raises(TypeError, lambda: td - np.array([1])) - pytest.raises(TypeError, lambda: np.array([1]) - td) - - expected = pd.to_timedelta(['2 days']).values - tm.assert_numpy_array_equal(td * np.array([2]), expected) - tm.assert_numpy_array_equal(np.array([2]) * td, expected) - pytest.raises(TypeError, lambda: td * other) - pytest.raises(TypeError, lambda: other * td) - - tm.assert_numpy_array_equal(td / other, - np.array([1], dtype=np.float64)) - if LooseVersion(np.__version__) >= LooseVersion('1.8'): - tm.assert_numpy_array_equal(other / td, - np.array([1], dtype=np.float64)) - - # timedelta, datetime - other = pd.to_datetime(['2000-01-01']).values - expected = pd.to_datetime(['2000-01-02']).values - tm.assert_numpy_array_equal(td + other, expected) - if LooseVersion(np.__version__) >= LooseVersion('1.8'): - tm.assert_numpy_array_equal(other + td, expected) - - expected = pd.to_datetime(['1999-12-31']).values - tm.assert_numpy_array_equal(-td + other, expected) - if LooseVersion(np.__version__) >= LooseVersion('1.8'): - tm.assert_numpy_array_equal(other - td, expected) - - def test_ops_series_object(self): - # GH 13043 - s = pd.Series([pd.Timestamp('2015-01-01', tz='US/Eastern'), - pd.Timestamp('2015-01-01', tz='Asia/Tokyo')], - name='xxx') - assert s.dtype == object - - exp = pd.Series([pd.Timestamp('2015-01-02', tz='US/Eastern'), - pd.Timestamp('2015-01-02', tz='Asia/Tokyo')], - name='xxx') - tm.assert_series_equal(s + pd.Timedelta('1 days'), exp) - tm.assert_series_equal(pd.Timedelta('1 days') + s, exp) - - # object series & object series - s2 = pd.Series([pd.Timestamp('2015-01-03', tz='US/Eastern'), - pd.Timestamp('2015-01-05', tz='Asia/Tokyo')], - name='xxx') - assert s2.dtype == object - exp = pd.Series([pd.Timedelta('2 days'), pd.Timedelta('4 days')], - name='xxx') - tm.assert_series_equal(s2 - s, exp) - tm.assert_series_equal(s - s2, -exp) - - s = pd.Series([pd.Timedelta('01:00:00'), pd.Timedelta('02:00:00')], - name='xxx', dtype=object) - assert s.dtype == object - - exp = pd.Series([pd.Timedelta('01:30:00'), pd.Timedelta('02:30:00')], - name='xxx') - tm.assert_series_equal(s + pd.Timedelta('00:30:00'), exp) - tm.assert_series_equal(pd.Timedelta('00:30:00') + s, exp) - - def test_timedelta_ops_with_missing_values(self): - # setup - s1 = pd.to_timedelta(Series(['00:00:01'])) - s2 = pd.to_timedelta(Series(['00:00:02'])) - sn = pd.to_timedelta(Series([pd.NaT])) - df1 = pd.DataFrame(['00:00:01']).apply(pd.to_timedelta) - df2 = pd.DataFrame(['00:00:02']).apply(pd.to_timedelta) - dfn = pd.DataFrame([pd.NaT]).apply(pd.to_timedelta) - scalar1 = pd.to_timedelta('00:00:01') - scalar2 = pd.to_timedelta('00:00:02') - timedelta_NaT = pd.to_timedelta('NaT') - - actual = scalar1 + scalar1 - assert actual == scalar2 - actual = scalar2 - scalar1 - assert actual == scalar1 - - actual = s1 + s1 - tm.assert_series_equal(actual, s2) - actual = s2 - s1 - tm.assert_series_equal(actual, s1) - - actual = s1 + scalar1 - tm.assert_series_equal(actual, s2) - actual = scalar1 + s1 - tm.assert_series_equal(actual, s2) - actual = s2 - scalar1 - tm.assert_series_equal(actual, s1) - actual = -scalar1 + s2 - tm.assert_series_equal(actual, s1) - - actual = s1 + timedelta_NaT - tm.assert_series_equal(actual, sn) - actual = timedelta_NaT + s1 - tm.assert_series_equal(actual, sn) - actual = s1 - timedelta_NaT - tm.assert_series_equal(actual, sn) - actual = -timedelta_NaT + s1 - tm.assert_series_equal(actual, sn) - - with pytest.raises(TypeError): - s1 + np.nan - with pytest.raises(TypeError): - np.nan + s1 - with pytest.raises(TypeError): - s1 - np.nan - with pytest.raises(TypeError): - -np.nan + s1 - - actual = s1 + pd.NaT - tm.assert_series_equal(actual, sn) - actual = s2 - pd.NaT - tm.assert_series_equal(actual, sn) - - actual = s1 + df1 - tm.assert_frame_equal(actual, df2) - actual = s2 - df1 - tm.assert_frame_equal(actual, df1) - actual = df1 + s1 - tm.assert_frame_equal(actual, df2) - actual = df2 - s1 - tm.assert_frame_equal(actual, df1) - - actual = df1 + df1 - tm.assert_frame_equal(actual, df2) - actual = df2 - df1 - tm.assert_frame_equal(actual, df1) - - actual = df1 + scalar1 - tm.assert_frame_equal(actual, df2) - actual = df2 - scalar1 - tm.assert_frame_equal(actual, df1) - - actual = df1 + timedelta_NaT - tm.assert_frame_equal(actual, dfn) - actual = df1 - timedelta_NaT - tm.assert_frame_equal(actual, dfn) - - with pytest.raises(TypeError): - df1 + np.nan - with pytest.raises(TypeError): - df1 - np.nan - - actual = df1 + pd.NaT # NaT is datetime, not timedelta - tm.assert_frame_equal(actual, dfn) - actual = df1 - pd.NaT - tm.assert_frame_equal(actual, dfn) - def test_tdi_ops_attributes(self): rng = timedelta_range('2 days', periods=5, freq='2D', name='x') diff --git a/pandas/tests/series/test_arithmetic.py b/pandas/tests/series/test_arithmetic.py index 41064b84abc36..37ba1c91368b3 100644 --- a/pandas/tests/series/test_arithmetic.py +++ b/pandas/tests/series/test_arithmetic.py @@ -1,7 +1,6 @@ # -*- coding: utf-8 -*- import operator -import numpy as np import pytest from pandas import Series @@ -14,13 +13,6 @@ # Comparisons class TestSeriesComparison(object): - def test_compare_invalid(self): - # GH#8058 - # ops testing - a = pd.Series(np.random.randn(5), name=0) - b = pd.Series(np.random.randn(5)) - b.name = pd.Timestamp('2000-01-01') - tm.assert_series_equal(a / b, 1 / (b / a)) @pytest.mark.parametrize('opname', ['eq', 'ne', 'gt', 'lt', 'ge', 'le']) def test_ser_flex_cmp_return_dtypes(self, opname):