diff --git a/pandas/tests/arithmetic/test_numeric.py b/pandas/tests/arithmetic/test_numeric.py index 6694946902836..da1b3f1da5322 100644 --- a/pandas/tests/arithmetic/test_numeric.py +++ b/pandas/tests/arithmetic/test_numeric.py @@ -1055,3 +1055,22 @@ def test_numeric_compat2(self): (pd.RangeIndex(-100, -200, 3), 2, pd.RangeIndex(0))] for idx, div, expected in cases_exact: tm.assert_index_equal(idx // div, expected, exact=True) + + @pytest.mark.parametrize('dtype', [np.int64, np.float64]) + @pytest.mark.parametrize('delta', [1, 0, -1]) + def test_addsub_arithmetic(self, dtype, delta): + # GH#8142 + delta = dtype(delta) + index = pd.Index([10, 11, 12], dtype=dtype) + result = index + delta + expected = pd.Index(index.values + delta, dtype=dtype) + tm.assert_index_equal(result, expected) + + # this subtraction used to fail + result = index - delta + expected = pd.Index(index.values - delta, dtype=dtype) + tm.assert_index_equal(result, expected) + + tm.assert_index_equal(index + index, 2 * index) + tm.assert_index_equal(index - index, 0 * index) + assert not (index - index).empty diff --git a/pandas/tests/arithmetic/test_object.py b/pandas/tests/arithmetic/test_object.py index 9917c45ef6d12..29063ae3f50e3 100644 --- a/pandas/tests/arithmetic/test_object.py +++ b/pandas/tests/arithmetic/test_object.py @@ -2,6 +2,7 @@ # Arithmetc tests for DataFrame/Series/Index/Array classes that should # behave identically. # Specifically for object dtype +from decimal import Decimal import operator import numpy as np @@ -224,3 +225,90 @@ def test_mixed_timezone_series_ops_object(self): name='xxx') tm.assert_series_equal(ser + pd.Timedelta('00:30:00'), exp) tm.assert_series_equal(pd.Timedelta('00:30:00') + ser, exp) + + # TODO: cleanup & parametrize over box + def test_iadd_preserves_name(self): + # GH#17067, GH#19723 __iadd__ and __isub__ should preserve index name + ser = pd.Series([1, 2, 3]) + ser.index.name = 'foo' + + ser.index += 1 + assert ser.index.name == "foo" + + ser.index -= 1 + assert ser.index.name == "foo" + + def test_add_string(self): + # from bug report + index = pd.Index(['a', 'b', 'c']) + index2 = index + 'foo' + + assert 'a' not in index2 + assert 'afoo' in index2 + + def test_iadd_string(self): + index = pd.Index(['a', 'b', 'c']) + # doesn't fail test unless there is a check before `+=` + assert 'a' in index + + index += '_x' + assert 'a_x' in index + + def test_add(self): + index = tm.makeStringIndex(100) + expected = pd.Index(index.values * 2) + tm.assert_index_equal(index + index, expected) + tm.assert_index_equal(index + index.tolist(), expected) + tm.assert_index_equal(index.tolist() + index, expected) + + # test add and radd + index = pd.Index(list('abc')) + expected = pd.Index(['a1', 'b1', 'c1']) + tm.assert_index_equal(index + '1', expected) + expected = pd.Index(['1a', '1b', '1c']) + tm.assert_index_equal('1' + index, expected) + + def test_sub_fail(self): + index = tm.makeStringIndex(100) + with pytest.raises(TypeError): + index - 'a' + with pytest.raises(TypeError): + index - index + with pytest.raises(TypeError): + index - index.tolist() + with pytest.raises(TypeError): + index.tolist() - index + + def test_sub_object(self): + # GH#19369 + index = pd.Index([Decimal(1), Decimal(2)]) + expected = pd.Index([Decimal(0), Decimal(1)]) + + result = index - Decimal(1) + tm.assert_index_equal(result, expected) + + result = index - pd.Index([Decimal(1), Decimal(1)]) + tm.assert_index_equal(result, expected) + + with pytest.raises(TypeError): + index - 'foo' + + with pytest.raises(TypeError): + index - np.array([2, 'foo']) + + def test_rsub_object(self): + # GH#19369 + index = pd.Index([Decimal(1), Decimal(2)]) + expected = pd.Index([Decimal(1), Decimal(0)]) + + result = Decimal(2) - index + tm.assert_index_equal(result, expected) + + result = np.array([Decimal(2), Decimal(2)]) - index + tm.assert_index_equal(result, expected) + + with pytest.raises(TypeError): + 'foo' - index + + with pytest.raises(TypeError): + np.array([True, pd.Timestamp.now()]) - index diff --git a/pandas/tests/indexes/datetimes/test_ops.py b/pandas/tests/indexes/datetimes/test_ops.py index 4be4372f65dcc..2a546af79931e 100644 --- a/pandas/tests/indexes/datetimes/test_ops.py +++ b/pandas/tests/indexes/datetimes/test_ops.py @@ -47,59 +47,6 @@ def test_ops_properties_basic(self): assert s.day == 10 pytest.raises(AttributeError, lambda: s.weekday) - def test_minmax_tz(self, tz_naive_fixture): - tz = tz_naive_fixture - # monotonic - idx1 = pd.DatetimeIndex(['2011-01-01', '2011-01-02', - '2011-01-03'], tz=tz) - assert idx1.is_monotonic - - # non-monotonic - idx2 = pd.DatetimeIndex(['2011-01-01', pd.NaT, '2011-01-03', - '2011-01-02', pd.NaT], tz=tz) - assert not idx2.is_monotonic - - for idx in [idx1, idx2]: - assert idx.min() == Timestamp('2011-01-01', tz=tz) - assert idx.max() == Timestamp('2011-01-03', tz=tz) - assert idx.argmin() == 0 - assert idx.argmax() == 2 - - @pytest.mark.parametrize('op', ['min', 'max']) - def test_minmax_nat(self, op): - # Return NaT - obj = DatetimeIndex([]) - assert pd.isna(getattr(obj, op)()) - - obj = DatetimeIndex([pd.NaT]) - assert pd.isna(getattr(obj, op)()) - - obj = DatetimeIndex([pd.NaT, pd.NaT, pd.NaT]) - assert pd.isna(getattr(obj, op)()) - - def test_numpy_minmax(self): - dr = pd.date_range(start='2016-01-15', end='2016-01-20') - - assert np.min(dr) == Timestamp('2016-01-15 00:00:00', freq='D') - assert np.max(dr) == Timestamp('2016-01-20 00:00:00', freq='D') - - errmsg = "the 'out' parameter is not supported" - with pytest.raises(ValueError, match=errmsg): - np.min(dr, out=0) - - with pytest.raises(ValueError, match=errmsg): - np.max(dr, out=0) - - assert np.argmin(dr) == 0 - assert np.argmax(dr) == 5 - - errmsg = "the 'out' parameter is not supported" - with pytest.raises(ValueError, match=errmsg): - np.argmin(dr, out=0) - - with pytest.raises(ValueError, match=errmsg): - np.argmax(dr, out=0) - def test_repeat_range(self, tz_naive_fixture): tz = tz_naive_fixture rng = date_range('1/1/2000', '1/1/2001') diff --git a/pandas/tests/indexes/period/test_ops.py b/pandas/tests/indexes/period/test_ops.py index eebff39fdf46f..8b022268897b6 100644 --- a/pandas/tests/indexes/period/test_ops.py +++ b/pandas/tests/indexes/period/test_ops.py @@ -3,7 +3,7 @@ import pytest import pandas as pd -from pandas import DatetimeIndex, Index, NaT, Period, PeriodIndex, Series +from pandas import DatetimeIndex, Index, NaT, PeriodIndex, Series from pandas.core.arrays import PeriodArray from pandas.tests.test_base import Ops import pandas.util.testing as tm @@ -24,61 +24,6 @@ def test_ops_properties(self): self.check_ops_properties(PeriodArray._object_ops, f) self.check_ops_properties(PeriodArray._bool_ops, f) - def test_minmax(self): - - # monotonic - idx1 = pd.PeriodIndex([NaT, '2011-01-01', '2011-01-02', - '2011-01-03'], freq='D') - assert idx1.is_monotonic - - # non-monotonic - idx2 = pd.PeriodIndex(['2011-01-01', NaT, '2011-01-03', - '2011-01-02', NaT], freq='D') - assert not idx2.is_monotonic - - for idx in [idx1, idx2]: - assert idx.min() == pd.Period('2011-01-01', freq='D') - assert idx.max() == pd.Period('2011-01-03', freq='D') - assert idx1.argmin() == 1 - assert idx2.argmin() == 0 - assert idx1.argmax() == 3 - assert idx2.argmax() == 2 - - for op in ['min', 'max']: - # Return NaT - obj = PeriodIndex([], freq='M') - result = getattr(obj, op)() - assert result is NaT - - obj = PeriodIndex([NaT], freq='M') - result = getattr(obj, op)() - assert result is NaT - - obj = PeriodIndex([NaT, NaT, NaT], freq='M') - result = getattr(obj, op)() - assert result is NaT - - def test_numpy_minmax(self): - pr = pd.period_range(start='2016-01-15', end='2016-01-20') - - assert np.min(pr) == Period('2016-01-15', freq='D') - assert np.max(pr) == Period('2016-01-20', freq='D') - - errmsg = "the 'out' parameter is not supported" - with pytest.raises(ValueError, match=errmsg): - np.min(pr, out=0) - with pytest.raises(ValueError, match=errmsg): - np.max(pr, out=0) - - assert np.argmin(pr) == 0 - assert np.argmax(pr) == 5 - - errmsg = "the 'out' parameter is not supported" - with pytest.raises(ValueError, match=errmsg): - np.argmin(pr, out=0) - with pytest.raises(ValueError, match=errmsg): - np.argmax(pr, out=0) - def test_resolution(self): for freq, expected in zip(['A', 'Q', 'M', 'D', 'H', 'T', 'S', 'L', 'U'], diff --git a/pandas/tests/indexes/test_base.py b/pandas/tests/indexes/test_base.py index d75800b763cb9..7f6b76f7442af 100644 --- a/pandas/tests/indexes/test_base.py +++ b/pandas/tests/indexes/test_base.py @@ -2,7 +2,6 @@ from collections import defaultdict from datetime import datetime, timedelta -from decimal import Decimal import math import sys @@ -834,61 +833,6 @@ def test_union_dt_as_obj(self): tm.assert_contains_all(self.strIndex, secondCat) tm.assert_contains_all(self.dateIndex, firstCat) - def test_add(self): - index = self.strIndex - expected = Index(self.strIndex.values * 2) - tm.assert_index_equal(index + index, expected) - tm.assert_index_equal(index + index.tolist(), expected) - tm.assert_index_equal(index.tolist() + index, expected) - - # test add and radd - index = Index(list('abc')) - expected = Index(['a1', 'b1', 'c1']) - tm.assert_index_equal(index + '1', expected) - expected = Index(['1a', '1b', '1c']) - tm.assert_index_equal('1' + index, expected) - - def test_sub_fail(self): - index = self.strIndex - pytest.raises(TypeError, lambda: index - 'a') - pytest.raises(TypeError, lambda: index - index) - pytest.raises(TypeError, lambda: index - index.tolist()) - pytest.raises(TypeError, lambda: index.tolist() - index) - - def test_sub_object(self): - # GH#19369 - index = pd.Index([Decimal(1), Decimal(2)]) - expected = pd.Index([Decimal(0), Decimal(1)]) - - result = index - Decimal(1) - tm.assert_index_equal(result, expected) - - result = index - pd.Index([Decimal(1), Decimal(1)]) - tm.assert_index_equal(result, expected) - - with pytest.raises(TypeError): - index - 'foo' - - with pytest.raises(TypeError): - index - np.array([2, 'foo']) - - def test_rsub_object(self): - # GH#19369 - index = pd.Index([Decimal(1), Decimal(2)]) - expected = pd.Index([Decimal(1), Decimal(0)]) - - result = Decimal(2) - index - tm.assert_index_equal(result, expected) - - result = np.array([Decimal(2), Decimal(2)]) - index - tm.assert_index_equal(result, expected) - - with pytest.raises(TypeError): - 'foo' - index - - with pytest.raises(TypeError): - np.array([True, pd.Timestamp.now()]) - index - def test_map_identity_mapping(self): # GH 12766 # TODO: replace with fixture @@ -1008,22 +952,6 @@ def test_append_empty_preserve_name(self, name, expected): result = left.append(right) assert result.name == expected - def test_add_string(self): - # from bug report - index = Index(['a', 'b', 'c']) - index2 = index + 'foo' - - assert 'a' not in index2 - assert 'afoo' in index2 - - def test_iadd_string(self): - index = pd.Index(['a', 'b', 'c']) - # doesn't fail test unless there is a check before `+=` - assert 'a' in index - - index += '_x' - assert 'a_x' in index - @pytest.mark.parametrize("second_name,expected", [ (None, None), ('name', 'name')]) @pytest.mark.parametrize("sort", [True, False]) @@ -2146,36 +2074,6 @@ def test_string_index_repr_with_unicode_option_compat(self, index, result = unicode(index) # noqa assert result == expected - @pytest.mark.parametrize('dtype', [np.int64, np.float64]) - @pytest.mark.parametrize('delta', [1, 0, -1]) - def test_addsub_arithmetic(self, dtype, delta): - # GH 8142 - delta = dtype(delta) - index = pd.Index([10, 11, 12], dtype=dtype) - result = index + delta - expected = pd.Index(index.values + delta, dtype=dtype) - tm.assert_index_equal(result, expected) - - # this subtraction used to fail - result = index - delta - expected = pd.Index(index.values - delta, dtype=dtype) - tm.assert_index_equal(result, expected) - - tm.assert_index_equal(index + index, 2 * index) - tm.assert_index_equal(index - index, 0 * index) - assert not (index - index).empty - - def test_iadd_preserves_name(self): - # GH#17067, GH#19723 __iadd__ and __isub__ should preserve index name - ser = pd.Series([1, 2, 3]) - ser.index.name = 'foo' - - ser.index += 1 - assert ser.index.name == "foo" - - ser.index -= 1 - assert ser.index.name == "foo" - def test_cached_properties_not_settable(self): index = pd.Index([1, 2, 3]) with pytest.raises(AttributeError, match="Can't set attribute"): diff --git a/pandas/tests/indexes/test_category.py b/pandas/tests/indexes/test_category.py index d85568ce67d16..582d466c6178e 100644 --- a/pandas/tests/indexes/test_category.py +++ b/pandas/tests/indexes/test_category.py @@ -251,17 +251,6 @@ def test_contains(self): list('aabbca') + [np.nan], categories=list('cabdef')) assert np.nan in ci - def test_min_max(self): - - ci = self.create_index(ordered=False) - pytest.raises(TypeError, lambda: ci.min()) - pytest.raises(TypeError, lambda: ci.max()) - - ci = self.create_index(ordered=True) - - assert ci.min() == 'c' - assert ci.max() == 'b' - def test_map(self): ci = pd.CategoricalIndex(list('ABABC'), categories=list('CBA'), ordered=True) diff --git a/pandas/tests/indexes/test_range.py b/pandas/tests/indexes/test_range.py index 7cb62c275e621..30822975a3ea0 100644 --- a/pandas/tests/indexes/test_range.py +++ b/pandas/tests/indexes/test_range.py @@ -8,7 +8,7 @@ from pandas.compat import PY3, range, u import pandas as pd -from pandas import Float64Index, Index, Int64Index, RangeIndex, Series, isna +from pandas import Float64Index, Index, Int64Index, RangeIndex, Series import pandas.util.testing as tm from .test_numeric import Numeric @@ -884,30 +884,3 @@ def test_append(self): # Append single item rather than list result2 = indices[0].append(indices[1]) tm.assert_index_equal(result2, expected, exact=True) - - @pytest.mark.parametrize('start,stop,step', - [(0, 400, 3), (500, 0, -6), (-10**6, 10**6, 4), - (10**6, -10**6, -4), (0, 10, 20)]) - def test_max_min(self, start, stop, step): - # GH17607 - idx = RangeIndex(start, stop, step) - expected = idx._int64index.max() - result = idx.max() - assert result == expected - - # skipna should be irrelevant since RangeIndex should never have NAs - result2 = idx.max(skipna=False) - assert result2 == expected - - expected = idx._int64index.min() - result = idx.min() - assert result == expected - - # skipna should be irrelevant since RangeIndex should never have NAs - result2 = idx.min(skipna=False) - assert result2 == expected - - # empty - idx = RangeIndex(start, stop, -step) - assert isna(idx.max()) - assert isna(idx.min()) diff --git a/pandas/tests/indexes/timedeltas/test_ops.py b/pandas/tests/indexes/timedeltas/test_ops.py index 97898dd8942f8..40377e4362b75 100644 --- a/pandas/tests/indexes/timedeltas/test_ops.py +++ b/pandas/tests/indexes/timedeltas/test_ops.py @@ -1,4 +1,3 @@ -from datetime import timedelta import numpy as np import pytest @@ -6,9 +5,7 @@ from pandas.core.dtypes.generic import ABCDateOffset import pandas as pd -from pandas import ( - Series, Timedelta, TimedeltaIndex, Timestamp, timedelta_range, - to_timedelta) +from pandas import Series, TimedeltaIndex, timedelta_range from pandas.tests.test_base import Ops import pandas.util.testing as tm @@ -27,54 +24,6 @@ def test_ops_properties(self): self.check_ops_properties(TimedeltaIndex._field_ops, f) self.check_ops_properties(TimedeltaIndex._object_ops, f) - def test_minmax(self): - - # monotonic - idx1 = TimedeltaIndex(['1 days', '2 days', '3 days']) - assert idx1.is_monotonic - - # non-monotonic - idx2 = TimedeltaIndex(['1 days', np.nan, '3 days', 'NaT']) - assert not idx2.is_monotonic - - for idx in [idx1, idx2]: - assert idx.min() == Timedelta('1 days') - assert idx.max() == Timedelta('3 days') - assert idx.argmin() == 0 - assert idx.argmax() == 2 - - for op in ['min', 'max']: - # Return NaT - obj = TimedeltaIndex([]) - assert pd.isna(getattr(obj, op)()) - - obj = TimedeltaIndex([pd.NaT]) - assert pd.isna(getattr(obj, op)()) - - obj = TimedeltaIndex([pd.NaT, pd.NaT, pd.NaT]) - assert pd.isna(getattr(obj, op)()) - - def test_numpy_minmax(self): - td = timedelta_range('16815 days', '16820 days', freq='D') - - assert np.min(td) == Timedelta('16815 days') - assert np.max(td) == Timedelta('16820 days') - - errmsg = "the 'out' parameter is not supported" - with pytest.raises(ValueError, match=errmsg): - np.min(td, out=0) - with pytest.raises(ValueError, match=errmsg): - np.max(td, out=0) - - assert np.argmin(td) == 0 - assert np.argmax(td) == 5 - - errmsg = "the 'out' parameter is not supported" - with pytest.raises(ValueError, match=errmsg): - np.argmin(td, out=0) - with pytest.raises(ValueError, match=errmsg): - np.argmax(td, out=0) - def test_value_counts_unique(self): # GH 7735 @@ -330,61 +279,3 @@ def test_freq_setter_errors(self): # setting with non-freq string with pytest.raises(ValueError, match='Invalid frequency'): idx.freq = 'foo' - - -class TestTimedeltas(object): - - def test_timedelta_ops(self): - # GH4984 - # make sure ops return Timedelta - s = Series([Timestamp('20130101') + timedelta(seconds=i * i) - for i in range(10)]) - td = s.diff() - - result = td.mean() - expected = to_timedelta(timedelta(seconds=9)) - assert result == expected - - result = td.to_frame().mean() - assert result[0] == expected - - result = td.quantile(.1) - expected = Timedelta(np.timedelta64(2600, 'ms')) - assert result == expected - - result = td.median() - expected = to_timedelta('00:00:09') - assert result == expected - - result = td.to_frame().median() - assert result[0] == expected - - # GH 6462 - # consistency in returned values for sum - result = td.sum() - expected = to_timedelta('00:01:21') - assert result == expected - - result = td.to_frame().sum() - assert result[0] == expected - - # std - result = td.std() - expected = to_timedelta(Series(td.dropna().values).std()) - assert result == expected - - result = td.to_frame().std() - assert result[0] == expected - - # invalid ops - for op in ['skew', 'kurt', 'sem', 'prod']: - pytest.raises(TypeError, getattr(td, op)) - - # GH 10040 - # make sure NaT is properly handled by median() - s = Series([Timestamp('2015-02-03'), Timestamp('2015-02-07')]) - assert s.diff().median() == timedelta(days=4) - - s = Series([Timestamp('2015-02-03'), Timestamp('2015-02-07'), - Timestamp('2015-02-15')]) - assert s.diff().median() == timedelta(days=6) diff --git a/pandas/tests/reductions/test_reductions.py b/pandas/tests/reductions/test_reductions.py index d27308029fa19..c7bb667f71fac 100644 --- a/pandas/tests/reductions/test_reductions.py +++ b/pandas/tests/reductions/test_reductions.py @@ -1,11 +1,14 @@ # -*- coding: utf-8 -*- -from datetime import datetime +from datetime import datetime, timedelta import numpy as np import pytest import pandas as pd -from pandas import Categorical, DataFrame, Index, PeriodIndex, Series, compat +from pandas import ( + Categorical, DataFrame, DatetimeIndex, Index, NaT, Period, PeriodIndex, + RangeIndex, Series, Timedelta, TimedeltaIndex, Timestamp, compat, isna, + timedelta_range, to_timedelta) from pandas.core import nanops import pandas.util.testing as tm @@ -136,6 +139,266 @@ def test_nanops(self): assert obj.argmax(skipna=False) == -1 +class TestIndexReductions(object): + # Note: the name TestIndexReductions indicates these tests + # were moved from a Index-specific test file, _not_ that these tests are + # intended long-term to be Index-specific + + @pytest.mark.parametrize('start,stop,step', + [(0, 400, 3), (500, 0, -6), (-10**6, 10**6, 4), + (10**6, -10**6, -4), (0, 10, 20)]) + def test_max_min_range(self, start, stop, step): + # GH#17607 + idx = RangeIndex(start, stop, step) + expected = idx._int64index.max() + result = idx.max() + assert result == expected + + # skipna should be irrelevant since RangeIndex should never have NAs + result2 = idx.max(skipna=False) + assert result2 == expected + + expected = idx._int64index.min() + result = idx.min() + assert result == expected + + # skipna should be irrelevant since RangeIndex should never have NAs + result2 = idx.min(skipna=False) + assert result2 == expected + + # empty + idx = RangeIndex(start, stop, -step) + assert isna(idx.max()) + assert isna(idx.min()) + + def test_minmax_timedelta64(self): + + # monotonic + idx1 = TimedeltaIndex(['1 days', '2 days', '3 days']) + assert idx1.is_monotonic + + # non-monotonic + idx2 = TimedeltaIndex(['1 days', np.nan, '3 days', 'NaT']) + assert not idx2.is_monotonic + + for idx in [idx1, idx2]: + assert idx.min() == Timedelta('1 days') + assert idx.max() == Timedelta('3 days') + assert idx.argmin() == 0 + assert idx.argmax() == 2 + + for op in ['min', 'max']: + # Return NaT + obj = TimedeltaIndex([]) + assert pd.isna(getattr(obj, op)()) + + obj = TimedeltaIndex([pd.NaT]) + assert pd.isna(getattr(obj, op)()) + + obj = TimedeltaIndex([pd.NaT, pd.NaT, pd.NaT]) + assert pd.isna(getattr(obj, op)()) + + def test_numpy_minmax_timedelta64(self): + td = timedelta_range('16815 days', '16820 days', freq='D') + + assert np.min(td) == Timedelta('16815 days') + assert np.max(td) == Timedelta('16820 days') + + errmsg = "the 'out' parameter is not supported" + with pytest.raises(ValueError, match=errmsg): + np.min(td, out=0) + with pytest.raises(ValueError, match=errmsg): + np.max(td, out=0) + + assert np.argmin(td) == 0 + assert np.argmax(td) == 5 + + errmsg = "the 'out' parameter is not supported" + with pytest.raises(ValueError, match=errmsg): + np.argmin(td, out=0) + with pytest.raises(ValueError, match=errmsg): + np.argmax(td, out=0) + + def test_timedelta_ops(self): + # GH#4984 + # make sure ops return Timedelta + s = Series([Timestamp('20130101') + timedelta(seconds=i * i) + for i in range(10)]) + td = s.diff() + + result = td.mean() + expected = to_timedelta(timedelta(seconds=9)) + assert result == expected + + result = td.to_frame().mean() + assert result[0] == expected + + result = td.quantile(.1) + expected = Timedelta(np.timedelta64(2600, 'ms')) + assert result == expected + + result = td.median() + expected = to_timedelta('00:00:09') + assert result == expected + + result = td.to_frame().median() + assert result[0] == expected + + # GH#6462 + # consistency in returned values for sum + result = td.sum() + expected = to_timedelta('00:01:21') + assert result == expected + + result = td.to_frame().sum() + assert result[0] == expected + + # std + result = td.std() + expected = to_timedelta(Series(td.dropna().values).std()) + assert result == expected + + result = td.to_frame().std() + assert result[0] == expected + + # invalid ops + for op in ['skew', 'kurt', 'sem', 'prod']: + pytest.raises(TypeError, getattr(td, op)) + + # GH#10040 + # make sure NaT is properly handled by median() + s = Series([Timestamp('2015-02-03'), Timestamp('2015-02-07')]) + assert s.diff().median() == timedelta(days=4) + + s = Series([Timestamp('2015-02-03'), Timestamp('2015-02-07'), + Timestamp('2015-02-15')]) + assert s.diff().median() == timedelta(days=6) + + def test_minmax_tz(self, tz_naive_fixture): + tz = tz_naive_fixture + # monotonic + idx1 = pd.DatetimeIndex(['2011-01-01', '2011-01-02', + '2011-01-03'], tz=tz) + assert idx1.is_monotonic + + # non-monotonic + idx2 = pd.DatetimeIndex(['2011-01-01', pd.NaT, '2011-01-03', + '2011-01-02', pd.NaT], tz=tz) + assert not idx2.is_monotonic + + for idx in [idx1, idx2]: + assert idx.min() == Timestamp('2011-01-01', tz=tz) + assert idx.max() == Timestamp('2011-01-03', tz=tz) + assert idx.argmin() == 0 + assert idx.argmax() == 2 + + @pytest.mark.parametrize('op', ['min', 'max']) + def test_minmax_nat_datetime64(self, op): + # Return NaT + obj = DatetimeIndex([]) + assert pd.isna(getattr(obj, op)()) + + obj = DatetimeIndex([pd.NaT]) + assert pd.isna(getattr(obj, op)()) + + obj = DatetimeIndex([pd.NaT, pd.NaT, pd.NaT]) + assert pd.isna(getattr(obj, op)()) + + def test_numpy_minmax_datetime64(self): + dr = pd.date_range(start='2016-01-15', end='2016-01-20') + + assert np.min(dr) == Timestamp('2016-01-15 00:00:00', freq='D') + assert np.max(dr) == Timestamp('2016-01-20 00:00:00', freq='D') + + errmsg = "the 'out' parameter is not supported" + with pytest.raises(ValueError, match=errmsg): + np.min(dr, out=0) + + with pytest.raises(ValueError, match=errmsg): + np.max(dr, out=0) + + assert np.argmin(dr) == 0 + assert np.argmax(dr) == 5 + + errmsg = "the 'out' parameter is not supported" + with pytest.raises(ValueError, match=errmsg): + np.argmin(dr, out=0) + + with pytest.raises(ValueError, match=errmsg): + np.argmax(dr, out=0) + + def test_minmax_period(self): + + # monotonic + idx1 = pd.PeriodIndex([NaT, '2011-01-01', '2011-01-02', + '2011-01-03'], freq='D') + assert idx1.is_monotonic + + # non-monotonic + idx2 = pd.PeriodIndex(['2011-01-01', NaT, '2011-01-03', + '2011-01-02', NaT], freq='D') + assert not idx2.is_monotonic + + for idx in [idx1, idx2]: + assert idx.min() == pd.Period('2011-01-01', freq='D') + assert idx.max() == pd.Period('2011-01-03', freq='D') + assert idx1.argmin() == 1 + assert idx2.argmin() == 0 + assert idx1.argmax() == 3 + assert idx2.argmax() == 2 + + for op in ['min', 'max']: + # Return NaT + obj = PeriodIndex([], freq='M') + result = getattr(obj, op)() + assert result is NaT + + obj = PeriodIndex([NaT], freq='M') + result = getattr(obj, op)() + assert result is NaT + + obj = PeriodIndex([NaT, NaT, NaT], freq='M') + result = getattr(obj, op)() + assert result is NaT + + def test_numpy_minmax_period(self): + pr = pd.period_range(start='2016-01-15', end='2016-01-20') + + assert np.min(pr) == Period('2016-01-15', freq='D') + assert np.max(pr) == Period('2016-01-20', freq='D') + + errmsg = "the 'out' parameter is not supported" + with pytest.raises(ValueError, match=errmsg): + np.min(pr, out=0) + with pytest.raises(ValueError, match=errmsg): + np.max(pr, out=0) + + assert np.argmin(pr) == 0 + assert np.argmax(pr) == 5 + + errmsg = "the 'out' parameter is not supported" + with pytest.raises(ValueError, match=errmsg): + np.argmin(pr, out=0) + with pytest.raises(ValueError, match=errmsg): + np.argmax(pr, out=0) + + def test_min_max_categorical(self): + + ci = pd.CategoricalIndex(list('aabbca'), + categories=list('cab'), + ordered=False) + with pytest.raises(TypeError): + ci.min() + with pytest.raises(TypeError): + ci.max() + + ci = pd.CategoricalIndex(list('aabbca'), + categories=list('cab'), + ordered=True) + assert ci.min() == 'c' + assert ci.max() == 'b' + + class TestSeriesReductions(object): # Note: the name TestSeriesReductions indicates these tests # were moved from a series-specific test file, _not_ that these tests are diff --git a/pandas/tests/test_nanops.py b/pandas/tests/test_nanops.py index 1e65118194be7..4bcd16a86e865 100644 --- a/pandas/tests/test_nanops.py +++ b/pandas/tests/test_nanops.py @@ -27,21 +27,21 @@ def setup_method(self, method): np.random.seed(11235) nanops._USE_BOTTLENECK = False - self.arr_shape = (11, 7, 5) + arr_shape = (11, 7, 5) - self.arr_float = np.random.randn(*self.arr_shape) - self.arr_float1 = np.random.randn(*self.arr_shape) + self.arr_float = np.random.randn(*arr_shape) + self.arr_float1 = np.random.randn(*arr_shape) self.arr_complex = self.arr_float + self.arr_float1 * 1j - self.arr_int = np.random.randint(-10, 10, self.arr_shape) - self.arr_bool = np.random.randint(0, 2, self.arr_shape) == 0 + self.arr_int = np.random.randint(-10, 10, arr_shape) + self.arr_bool = np.random.randint(0, 2, arr_shape) == 0 self.arr_str = np.abs(self.arr_float).astype('S') self.arr_utf = np.abs(self.arr_float).astype('U') self.arr_date = np.random.randint(0, 20000, - self.arr_shape).astype('M8[ns]') + arr_shape).astype('M8[ns]') self.arr_tdelta = np.random.randint(0, 20000, - self.arr_shape).astype('m8[ns]') + arr_shape).astype('m8[ns]') - self.arr_nan = np.tile(np.nan, self.arr_shape) + self.arr_nan = np.tile(np.nan, arr_shape) self.arr_float_nan = np.vstack([self.arr_float, self.arr_nan]) self.arr_float1_nan = np.vstack([self.arr_float1, self.arr_nan]) self.arr_nan_float1 = np.vstack([self.arr_nan, self.arr_float1]) @@ -49,22 +49,22 @@ def setup_method(self, method): self.arr_inf = self.arr_float * np.inf self.arr_float_inf = np.vstack([self.arr_float, self.arr_inf]) - self.arr_float1_inf = np.vstack([self.arr_float1, self.arr_inf]) - self.arr_inf_float1 = np.vstack([self.arr_inf, self.arr_float1]) - self.arr_inf_inf = np.vstack([self.arr_inf, self.arr_inf]) self.arr_nan_inf = np.vstack([self.arr_nan, self.arr_inf]) self.arr_float_nan_inf = np.vstack([self.arr_float, self.arr_nan, self.arr_inf]) - self.arr_nan_float1_inf = np.vstack([self.arr_float, self.arr_inf, - self.arr_nan]) self.arr_nan_nan_inf = np.vstack([self.arr_nan, self.arr_nan, self.arr_inf]) - self.arr_obj = np.vstack([self.arr_float.astype( - 'O'), self.arr_int.astype('O'), self.arr_bool.astype( - 'O'), self.arr_complex.astype('O'), self.arr_str.astype( - 'O'), self.arr_utf.astype('O'), self.arr_date.astype('O'), - self.arr_tdelta.astype('O')]) + self.arr_obj = np.vstack([ + self.arr_float.astype('O'), + self.arr_int.astype('O'), + self.arr_bool.astype('O'), + self.arr_complex.astype('O'), + self.arr_str.astype('O'), + self.arr_utf.astype('O'), + self.arr_date.astype('O'), + self.arr_tdelta.astype('O') + ]) with np.errstate(invalid='ignore'): self.arr_nan_nanj = self.arr_nan + self.arr_nan * 1j @@ -77,51 +77,19 @@ def setup_method(self, method): self.arr_float_2d = self.arr_float[:, :, 0] self.arr_float1_2d = self.arr_float1[:, :, 0] - self.arr_complex_2d = self.arr_complex[:, :, 0] - self.arr_int_2d = self.arr_int[:, :, 0] - self.arr_bool_2d = self.arr_bool[:, :, 0] - self.arr_str_2d = self.arr_str[:, :, 0] - self.arr_utf_2d = self.arr_utf[:, :, 0] - self.arr_date_2d = self.arr_date[:, :, 0] - self.arr_tdelta_2d = self.arr_tdelta[:, :, 0] self.arr_nan_2d = self.arr_nan[:, :, 0] self.arr_float_nan_2d = self.arr_float_nan[:, :, 0] self.arr_float1_nan_2d = self.arr_float1_nan[:, :, 0] self.arr_nan_float1_2d = self.arr_nan_float1[:, :, 0] - self.arr_nan_nan_2d = self.arr_nan_nan[:, :, 0] - self.arr_nan_nanj_2d = self.arr_nan_nanj[:, :, 0] - self.arr_complex_nan_2d = self.arr_complex_nan[:, :, 0] - - self.arr_inf_2d = self.arr_inf[:, :, 0] - self.arr_float_inf_2d = self.arr_float_inf[:, :, 0] - self.arr_nan_inf_2d = self.arr_nan_inf[:, :, 0] - self.arr_float_nan_inf_2d = self.arr_float_nan_inf[:, :, 0] - self.arr_nan_nan_inf_2d = self.arr_nan_nan_inf[:, :, 0] self.arr_float_1d = self.arr_float[:, 0, 0] self.arr_float1_1d = self.arr_float1[:, 0, 0] - self.arr_complex_1d = self.arr_complex[:, 0, 0] - self.arr_int_1d = self.arr_int[:, 0, 0] - self.arr_bool_1d = self.arr_bool[:, 0, 0] - self.arr_str_1d = self.arr_str[:, 0, 0] - self.arr_utf_1d = self.arr_utf[:, 0, 0] - self.arr_date_1d = self.arr_date[:, 0, 0] - self.arr_tdelta_1d = self.arr_tdelta[:, 0, 0] self.arr_nan_1d = self.arr_nan[:, 0, 0] self.arr_float_nan_1d = self.arr_float_nan[:, 0, 0] self.arr_float1_nan_1d = self.arr_float1_nan[:, 0, 0] self.arr_nan_float1_1d = self.arr_nan_float1[:, 0, 0] - self.arr_nan_nan_1d = self.arr_nan_nan[:, 0, 0] - self.arr_nan_nanj_1d = self.arr_nan_nanj[:, 0, 0] - self.arr_complex_nan_1d = self.arr_complex_nan[:, 0, 0] - - self.arr_inf_1d = self.arr_inf.ravel() - self.arr_float_inf_1d = self.arr_float_inf[:, 0, 0] - self.arr_nan_inf_1d = self.arr_nan_inf[:, 0, 0] - self.arr_float_nan_inf_1d = self.arr_float_nan_inf[:, 0, 0] - self.arr_nan_nan_inf_1d = self.arr_nan_nan_inf[:, 0, 0] def teardown_method(self, method): nanops._USE_BOTTLENECK = use_bn