From c7371b447589939ce28b9c42f3b411a80f4a26af Mon Sep 17 00:00:00 2001 From: Brock Date: Wed, 17 Feb 2021 13:20:47 -0800 Subject: [PATCH 1/5] TST/REF: PeriodIndex test_insert --- .../datetimes/{ => methods}/test_insert.py | 0 .../indexes/period/methods/test_insert.py | 18 ++++++++++++++++++ pandas/tests/indexes/period/test_period.py | 9 +-------- .../timedeltas/{ => methods}/test_insert.py | 0 4 files changed, 19 insertions(+), 8 deletions(-) rename pandas/tests/indexes/datetimes/{ => methods}/test_insert.py (100%) create mode 100644 pandas/tests/indexes/period/methods/test_insert.py rename pandas/tests/indexes/timedeltas/{ => methods}/test_insert.py (100%) diff --git a/pandas/tests/indexes/datetimes/test_insert.py b/pandas/tests/indexes/datetimes/methods/test_insert.py similarity index 100% rename from pandas/tests/indexes/datetimes/test_insert.py rename to pandas/tests/indexes/datetimes/methods/test_insert.py diff --git a/pandas/tests/indexes/period/methods/test_insert.py b/pandas/tests/indexes/period/methods/test_insert.py new file mode 100644 index 0000000000000..32bbe09d92567 --- /dev/null +++ b/pandas/tests/indexes/period/methods/test_insert.py @@ -0,0 +1,18 @@ +import numpy as np +import pytest + +from pandas import ( + NaT, + PeriodIndex, + period_range, +) +import pandas._testing as tm + + +class TestInsert: + @pytest.mark.parametrize("na", [np.nan, NaT, None]) + def test_insert(self, na): + # GH#18295 (test missing) + expected = PeriodIndex(["2017Q1", NaT, "2017Q2", "2017Q3", "2017Q4"], freq="Q") + result = period_range("2017Q1", periods=4, freq="Q").insert(1, na) + tm.assert_index_equal(result, expected) diff --git a/pandas/tests/indexes/period/test_period.py b/pandas/tests/indexes/period/test_period.py index af5ce1945a671..8574357f53b89 100644 --- a/pandas/tests/indexes/period/test_period.py +++ b/pandas/tests/indexes/period/test_period.py @@ -411,7 +411,7 @@ def test_convert_array_of_periods(self): result = Index(periods) assert isinstance(result, PeriodIndex) - def test_append_concat(self): + def test_append_concat(self): # TODO: pd.concat test # #1815 d1 = date_range("12/31/1990", "12/31/1999", freq="A-DEC") d2 = date_range("12/31/2000", "12/31/2009", freq="A-DEC") @@ -442,13 +442,6 @@ def test_map(self): exp = Index([x.ordinal for x in index]) tm.assert_index_equal(result, exp) - def test_insert(self): - # GH 18295 (test missing) - expected = PeriodIndex(["2017Q1", NaT, "2017Q2", "2017Q3", "2017Q4"], freq="Q") - for na in (np.nan, NaT, None): - result = period_range("2017Q1", periods=4, freq="Q").insert(1, na) - tm.assert_index_equal(result, expected) - @pytest.mark.parametrize( "msg, key", [ diff --git a/pandas/tests/indexes/timedeltas/test_insert.py b/pandas/tests/indexes/timedeltas/methods/test_insert.py similarity index 100% rename from pandas/tests/indexes/timedeltas/test_insert.py rename to pandas/tests/indexes/timedeltas/methods/test_insert.py From ede54215a8ccb341036fc6335f2e5426cd792e7f Mon Sep 17 00:00:00 2001 From: Brock Date: Wed, 17 Feb 2021 13:39:48 -0800 Subject: [PATCH 2/5] test_to_frame --- .../indexes/datetimes/methods/test_to_frame.py | 14 ++++++++++++++ pandas/tests/indexes/datetimes/test_datetime.py | 7 ------- 2 files changed, 14 insertions(+), 7 deletions(-) create mode 100644 pandas/tests/indexes/datetimes/methods/test_to_frame.py diff --git a/pandas/tests/indexes/datetimes/methods/test_to_frame.py b/pandas/tests/indexes/datetimes/methods/test_to_frame.py new file mode 100644 index 0000000000000..ec6254f52f4d5 --- /dev/null +++ b/pandas/tests/indexes/datetimes/methods/test_to_frame.py @@ -0,0 +1,14 @@ +from pandas import ( + DataFrame, + date_range, +) +import pandas._testing as tm + + +class TestToFrame: + def test_to_frame_datetime_tz(self): + # GH#25809 + idx = date_range(start="2019-01-01", end="2019-01-30", freq="D", tz="UTC") + result = idx.to_frame() + expected = DataFrame(idx, index=idx) + tm.assert_frame_equal(result, expected) diff --git a/pandas/tests/indexes/datetimes/test_datetime.py b/pandas/tests/indexes/datetimes/test_datetime.py index a93c68e0c6d9a..6eef43fe496dd 100644 --- a/pandas/tests/indexes/datetimes/test_datetime.py +++ b/pandas/tests/indexes/datetimes/test_datetime.py @@ -240,10 +240,3 @@ def test_asarray_tz_aware(self): result = np.asarray(idx, dtype=object) tm.assert_numpy_array_equal(result, expected) - - def test_to_frame_datetime_tz(self): - # GH 25809 - idx = date_range(start="2019-01-01", end="2019-01-30", freq="D", tz="UTC") - result = idx.to_frame() - expected = DataFrame(idx, index=idx) - tm.assert_frame_equal(result, expected) From 00f671dc3aec82d69ff780eb05b9d194670587cc Mon Sep 17 00:00:00 2001 From: Brock Date: Wed, 17 Feb 2021 14:00:51 -0800 Subject: [PATCH 3/5] TST/REF: collect tests by method --- pandas/tests/indexes/common.py | 10 +- pandas/tests/indexes/datetimes/test_asof.py | 14 ++ pandas/tests/indexes/test_base.py | 142 ++------------------ pandas/tests/indexes/test_setops.py | 132 +++++++++++++++++- 4 files changed, 153 insertions(+), 145 deletions(-) create mode 100644 pandas/tests/indexes/datetimes/test_asof.py diff --git a/pandas/tests/indexes/common.py b/pandas/tests/indexes/common.py index 0354e362dc4ac..f8daf23fb08a3 100644 --- a/pandas/tests/indexes/common.py +++ b/pandas/tests/indexes/common.py @@ -243,11 +243,6 @@ def test_copy_name2(self, index): with pytest.raises(TypeError, match=msg): index.copy(name=[["mario"]]) - def test_copy_dtype_deprecated(self, index): - # GH35853 - with tm.assert_produces_warning(FutureWarning, check_stacklevel=False): - index.copy(dtype=object) - def test_ensure_copied_data(self, index): # Check the "copy" argument of each Index.__new__ is honoured # GH12309 @@ -504,10 +499,9 @@ def test_format_empty(self): assert empty_idx.format() == [] assert empty_idx.format(name=True) == [""] - def test_hasnans_isnans(self, index): + def test_hasnans_isnans(self, index_flat): # GH 11343, added tests for hasnans / isnans - if isinstance(index, MultiIndex): - return + index = index_flat # cases in indices doesn't include NaN idx = index.copy(deep=True) diff --git a/pandas/tests/indexes/datetimes/test_asof.py b/pandas/tests/indexes/datetimes/test_asof.py new file mode 100644 index 0000000000000..c794aefc6a48b --- /dev/null +++ b/pandas/tests/indexes/datetimes/test_asof.py @@ -0,0 +1,14 @@ +from pandas import ( + Index, + Timestamp, + date_range, +) + + +class TestAsOf: + def test_asof_partial(self): + index = date_range("2010-01-01", periods=2, freq="m") + expected = Timestamp("2010-02-28") + result = index.asof("2010-02") + assert result == expected + assert not isinstance(result, Index) diff --git a/pandas/tests/indexes/test_base.py b/pandas/tests/indexes/test_base.py index 127f0432efa01..ccc345446beab 100644 --- a/pandas/tests/indexes/test_base.py +++ b/pandas/tests/indexes/test_base.py @@ -573,25 +573,19 @@ def test_asof_numeric_vs_bool_raises(self): with pytest.raises(TypeError, match=msg): right.asof(left) - def test_asof_datetime_partial(self): - index = date_range("2010-01-01", periods=2, freq="m") - expected = Timestamp("2010-02-28") - result = index.asof("2010-02") - assert result == expected - assert not isinstance(result, Index) - - def test_nanosecond_index_access(self): - s = Series([Timestamp("20130101")]).values.view("i8")[0] + # TODO: this tests Series.asof + def test_asof_nanosecond_index_access(self): + s = Timestamp("20130101").value r = DatetimeIndex([s + 50 + i for i in range(100)]) - x = Series(np.random.randn(100), index=r) + ser = Series(np.random.randn(100), index=r) - first_value = x.asof(x.index[0]) + first_value = ser.asof(ser.index[0]) # this does not yet work, as parsing strings is done via dateutil # assert first_value == x['2013-01-01 00:00:00.000000050+0000'] expected_ts = np_datetime64_compat("2013-01-01 00:00:00.000000050+0000", "ns") - assert first_value == x[Timestamp(expected_ts)] + assert first_value == ser[Timestamp(expected_ts)] @pytest.mark.parametrize("index", ["string"], indirect=True) def test_booleanindex(self, index): @@ -635,110 +629,6 @@ def test_empty_fancy_raises(self, index): with pytest.raises(IndexError, match=msg): index[empty_farr] - @pytest.mark.parametrize("index", ["string"], indirect=True) - def test_intersection(self, index, sort): - first = index[:20] - second = index[:10] - intersect = first.intersection(second, sort=sort) - if sort is None: - tm.assert_index_equal(intersect, second.sort_values()) - assert tm.equalContents(intersect, second) - - # Corner cases - inter = first.intersection(first, sort=sort) - assert inter is first - - @pytest.mark.parametrize( - "index2,keeps_name", - [ - (Index([3, 4, 5, 6, 7], name="index"), True), # preserve same name - (Index([3, 4, 5, 6, 7], name="other"), False), # drop diff names - (Index([3, 4, 5, 6, 7]), False), - ], - ) - def test_intersection_name_preservation(self, index2, keeps_name, sort): - index1 = Index([1, 2, 3, 4, 5], name="index") - expected = Index([3, 4, 5]) - result = index1.intersection(index2, sort) - - if keeps_name: - expected.name = "index" - - assert result.name == expected.name - tm.assert_index_equal(result, expected) - - @pytest.mark.parametrize("index", ["string"], indirect=True) - @pytest.mark.parametrize( - "first_name,second_name,expected_name", - [("A", "A", "A"), ("A", "B", None), (None, "B", None)], - ) - def test_intersection_name_preservation2( - self, index, first_name, second_name, expected_name, sort - ): - first = index[5:20] - second = index[:10] - first.name = first_name - second.name = second_name - intersect = first.intersection(second, sort=sort) - assert intersect.name == expected_name - - def test_chained_union(self, sort): - # Chained unions handles names correctly - i1 = Index([1, 2], name="i1") - i2 = Index([5, 6], name="i2") - i3 = Index([3, 4], name="i3") - union = i1.union(i2.union(i3, sort=sort), sort=sort) - expected = i1.union(i2, sort=sort).union(i3, sort=sort) - tm.assert_index_equal(union, expected) - - j1 = Index([1, 2], name="j1") - j2 = Index([], name="j2") - j3 = Index([], name="j3") - union = j1.union(j2.union(j3, sort=sort), sort=sort) - expected = j1.union(j2, sort=sort).union(j3, sort=sort) - tm.assert_index_equal(union, expected) - - @pytest.mark.parametrize("index", ["string"], indirect=True) - def test_union(self, index, sort): - first = index[5:20] - second = index[:10] - everything = index[:20] - - union = first.union(second, sort=sort) - if sort is None: - tm.assert_index_equal(union, everything.sort_values()) - assert tm.equalContents(union, everything) - - @pytest.mark.parametrize("klass", [np.array, Series, list]) - @pytest.mark.parametrize("index", ["string"], indirect=True) - def test_union_from_iterables(self, index, klass, sort): - # GH 10149 - first = index[5:20] - second = index[:10] - everything = index[:20] - - case = klass(second.values) - result = first.union(case, sort=sort) - if sort is None: - tm.assert_index_equal(result, everything.sort_values()) - assert tm.equalContents(result, everything) - - @pytest.mark.parametrize("index", ["string"], indirect=True) - def test_union_identity(self, index, sort): - first = index[5:20] - - union = first.union(first, sort=sort) - # i.e. identity is not preserved when sort is True - assert (union is first) is (not sort) - - # This should no longer be the same object, since [] is not consistent, - # both objects will be recast to dtype('O') - union = first.union([], sort=sort) - assert (union is first) is (not sort) - - union = Index([]).union(first, sort=sort) - assert (union is first) is (not sort) - def test_union_dt_as_obj(self, sort): # TODO: Replace with fixturesult index = self.create_index() @@ -1776,11 +1666,6 @@ def test_dropna_invalid_how_raises(self): with pytest.raises(ValueError, match=msg): Index([1, 2, 3]).dropna(how="xxx") - def test_get_combined_index(self): - result = _get_combined_index([]) - expected = Index([]) - tm.assert_index_equal(result, expected) - @pytest.mark.parametrize( "index", [ @@ -1813,16 +1698,6 @@ def test_str_to_bytes_raises(self): with pytest.raises(TypeError, match=msg): bytes(index) - def test_intersect_str_dates(self): - dt_dates = [datetime(2012, 2, 9), datetime(2012, 2, 22)] - - index1 = Index(dt_dates, dtype=object) - index2 = Index(["aa"], dtype=object) - result = index2.intersection(index1) - - expected = Index([], dtype=object) - tm.assert_index_equal(result, expected) - @pytest.mark.filterwarnings("ignore:elementwise comparison failed:FutureWarning") def test_index_with_tuple_bool(self): # GH34123 @@ -1868,6 +1743,11 @@ def test_ensure_index_mixed_closed_intervals(self): expected = Index(intervals, dtype=object) tm.assert_index_equal(result, expected) + def test_get_combined_index(self): + result = _get_combined_index([]) + expected = Index([]) + tm.assert_index_equal(result, expected) + @pytest.mark.parametrize( "opname", diff --git a/pandas/tests/indexes/test_setops.py b/pandas/tests/indexes/test_setops.py index 11514b9f04b59..9d216fda7c19a 100644 --- a/pandas/tests/indexes/test_setops.py +++ b/pandas/tests/indexes/test_setops.py @@ -2,16 +2,18 @@ The tests in this package are to ensure the proper resultant dtypes of set operations. """ +from datetime import datetime + import numpy as np import pytest from pandas.core.dtypes.common import is_dtype_equal -import pandas as pd from pandas import ( CategoricalIndex, DatetimeIndex, Float64Index, + Index, Int64Index, MultiIndex, RangeIndex, @@ -113,8 +115,8 @@ def test_compatible_inconsistent_pairs(idx_fact1, idx_fact2): def test_union_dtypes(left, right, expected, names): left = pandas_dtype(left) right = pandas_dtype(right) - a = pd.Index([], dtype=left, name=names[0]) - b = pd.Index([], dtype=right, name=names[1]) + a = Index([], dtype=left, name=names[0]) + b = Index([], dtype=right, name=names[1]) result = a.union(b) assert result.dtype == expected assert result.name == names[2] @@ -141,10 +143,10 @@ def test_dunder_inplace_setops_deprecated(index): @pytest.mark.parametrize("values", [[1, 2, 2, 3], [3, 3]]) def test_intersection_duplicates(values): # GH#31326 - a = pd.Index(values) - b = pd.Index([3, 3]) + a = Index(values) + b = Index([3, 3]) result = a.intersection(b) - expected = pd.Index([3]) + expected = Index([3]) tm.assert_index_equal(result, expected) @@ -495,3 +497,121 @@ def check_intersection_commutative(left, right): check_intersection_commutative(idx, idx_non_unique) assert idx.intersection(idx_non_unique).is_unique + + +class TestSetOpsUnsorted: + # These may eventually belong in a dtype-specific test_setops, or + # parametrized over a more general fixture + def test_intersect_str_dates(self): + dt_dates = [datetime(2012, 2, 9), datetime(2012, 2, 22)] + + index1 = Index(dt_dates, dtype=object) + index2 = Index(["aa"], dtype=object) + result = index2.intersection(index1) + + expected = Index([], dtype=object) + tm.assert_index_equal(result, expected) + + @pytest.mark.parametrize("index", ["string"], indirect=True) + def test_intersection(self, index, sort): + first = index[:20] + second = index[:10] + intersect = first.intersection(second, sort=sort) + if sort is None: + tm.assert_index_equal(intersect, second.sort_values()) + assert tm.equalContents(intersect, second) + + # Corner cases + inter = first.intersection(first, sort=sort) + assert inter is first + + @pytest.mark.parametrize( + "index2,keeps_name", + [ + (Index([3, 4, 5, 6, 7], name="index"), True), # preserve same name + (Index([3, 4, 5, 6, 7], name="other"), False), # drop diff names + (Index([3, 4, 5, 6, 7]), False), + ], + ) + def test_intersection_name_preservation(self, index2, keeps_name, sort): + index1 = Index([1, 2, 3, 4, 5], name="index") + expected = Index([3, 4, 5]) + result = index1.intersection(index2, sort) + + if keeps_name: + expected.name = "index" + + assert result.name == expected.name + tm.assert_index_equal(result, expected) + + @pytest.mark.parametrize("index", ["string"], indirect=True) + @pytest.mark.parametrize( + "first_name,second_name,expected_name", + [("A", "A", "A"), ("A", "B", None), (None, "B", None)], + ) + def test_intersection_name_preservation2( + self, index, first_name, second_name, expected_name, sort + ): + first = index[5:20] + second = index[:10] + first.name = first_name + second.name = second_name + intersect = first.intersection(second, sort=sort) + assert intersect.name == expected_name + + def test_chained_union(self, sort): + # Chained unions handles names correctly + i1 = Index([1, 2], name="i1") + i2 = Index([5, 6], name="i2") + i3 = Index([3, 4], name="i3") + union = i1.union(i2.union(i3, sort=sort), sort=sort) + expected = i1.union(i2, sort=sort).union(i3, sort=sort) + tm.assert_index_equal(union, expected) + + j1 = Index([1, 2], name="j1") + j2 = Index([], name="j2") + j3 = Index([], name="j3") + union = j1.union(j2.union(j3, sort=sort), sort=sort) + expected = j1.union(j2, sort=sort).union(j3, sort=sort) + tm.assert_index_equal(union, expected) + + @pytest.mark.parametrize("index", ["string"], indirect=True) + def test_union(self, index, sort): + first = index[5:20] + second = index[:10] + everything = index[:20] + + union = first.union(second, sort=sort) + if sort is None: + tm.assert_index_equal(union, everything.sort_values()) + assert tm.equalContents(union, everything) + + @pytest.mark.parametrize("klass", [np.array, Series, list]) + @pytest.mark.parametrize("index", ["string"], indirect=True) + def test_union_from_iterables(self, index, klass, sort): + # GH 10149 + first = index[5:20] + second = index[:10] + everything = index[:20] + + case = klass(second.values) + result = first.union(case, sort=sort) + if sort is None: + tm.assert_index_equal(result, everything.sort_values()) + assert tm.equalContents(result, everything) + + @pytest.mark.parametrize("index", ["string"], indirect=True) + def test_union_identity(self, index, sort): + first = index[5:20] + + union = first.union(first, sort=sort) + # i.e. identity is not preserved when sort is True + assert (union is first) is (not sort) + + # This should no longer be the same object, since [] is not consistent, + # both objects will be recast to dtype('O') + union = first.union([], sort=sort) + assert (union is first) is (not sort) + + union = Index([]).union(first, sort=sort) + assert (union is first) is (not sort) From dc16efbd80ae89066b3ba7ae2310d9bff39b6467 Mon Sep 17 00:00:00 2001 From: Brock Date: Wed, 17 Feb 2021 14:13:39 -0800 Subject: [PATCH 4/5] collect tests by method --- pandas/tests/indexes/test_base.py | 123 +--------------------------- pandas/tests/indexes/test_setops.py | 121 ++++++++++++++++++++++++++- 2 files changed, 121 insertions(+), 123 deletions(-) diff --git a/pandas/tests/indexes/test_base.py b/pandas/tests/indexes/test_base.py index ccc345446beab..0b43b6b1ead9c 100644 --- a/pandas/tests/indexes/test_base.py +++ b/pandas/tests/indexes/test_base.py @@ -5,7 +5,6 @@ ) from io import StringIO import math -import operator import re import numpy as np @@ -755,123 +754,6 @@ def test_append_empty_preserve_name(self, name, expected): result = left.append(right) assert result.name == expected - @pytest.mark.parametrize("index", ["string"], indirect=True) - @pytest.mark.parametrize("second_name,expected", [(None, None), ("name", "name")]) - def test_difference_name_preservation(self, index, second_name, expected, sort): - first = index[5:20] - second = index[:10] - answer = index[10:20] - - first.name = "name" - second.name = second_name - result = first.difference(second, sort=sort) - - assert tm.equalContents(result, answer) - - if expected is None: - assert result.name is None - else: - assert result.name == expected - - def test_difference_empty_arg(self, index, sort): - first = index[5:20] - first.name = "name" - result = first.difference([], sort) - - tm.assert_index_equal(result, first) - - @pytest.mark.parametrize("index", ["string"], indirect=True) - def test_difference_identity(self, index, sort): - first = index[5:20] - first.name = "name" - result = first.difference(first, sort) - - assert len(result) == 0 - assert result.name == first.name - - @pytest.mark.parametrize("index", ["string"], indirect=True) - def test_difference_sort(self, index, sort): - first = index[5:20] - second = index[:10] - - result = first.difference(second, sort) - expected = index[10:20] - - if sort is None: - expected = expected.sort_values() - - tm.assert_index_equal(result, expected) - - @pytest.mark.parametrize("opname", ["difference", "symmetric_difference"]) - def test_difference_incomparable(self, opname): - a = Index([3, Timestamp("2000"), 1]) - b = Index([2, Timestamp("1999"), 1]) - op = operator.methodcaller(opname, b) - - with tm.assert_produces_warning(RuntimeWarning): - # sort=None, the default - result = op(a) - expected = Index([3, Timestamp("2000"), 2, Timestamp("1999")]) - if opname == "difference": - expected = expected[:2] - tm.assert_index_equal(result, expected) - - # sort=False - op = operator.methodcaller(opname, b, sort=False) - result = op(a) - tm.assert_index_equal(result, expected) - - @pytest.mark.xfail(reason="Not implemented") - @pytest.mark.parametrize("opname", ["difference", "symmetric_difference"]) - def test_difference_incomparable_true(self, opname): - # TODO decide on True behaviour - # # sort=True, raises - a = Index([3, Timestamp("2000"), 1]) - b = Index([2, Timestamp("1999"), 1]) - op = operator.methodcaller(opname, b, sort=True) - - with pytest.raises(TypeError, match="Cannot compare"): - op(a) - - def test_symmetric_difference_mi(self, sort): - index1 = MultiIndex.from_tuples(zip(["foo", "bar", "baz"], [1, 2, 3])) - index2 = MultiIndex.from_tuples([("foo", 1), ("bar", 3)]) - result = index1.symmetric_difference(index2, sort=sort) - expected = MultiIndex.from_tuples([("bar", 2), ("baz", 3), ("bar", 3)]) - if sort is None: - expected = expected.sort_values() - tm.assert_index_equal(result, expected) - assert tm.equalContents(result, expected) - - @pytest.mark.parametrize( - "index2,expected", - [ - (Index([0, 1, np.nan]), Index([2.0, 3.0, 0.0])), - (Index([0, 1]), Index([np.nan, 2.0, 3.0, 0.0])), - ], - ) - def test_symmetric_difference_missing(self, index2, expected, sort): - # GH 13514 change: {nan} - {nan} == {} - # (GH 6444, sorting of nans, is no longer an issue) - index1 = Index([1, np.nan, 2, 3]) - - result = index1.symmetric_difference(index2, sort=sort) - if sort is None: - expected = expected.sort_values() - tm.assert_index_equal(result, expected) - - def test_symmetric_difference_non_index(self, sort): - index1 = Index([1, 2, 3, 4], name="index1") - index2 = np.array([2, 3, 4, 5]) - expected = Index([1, 5]) - result = index1.symmetric_difference(index2, sort=sort) - assert tm.equalContents(result, expected) - assert result.name == "index1" - - result = index1.symmetric_difference(index2, result_name="new_name", sort=sort) - assert tm.equalContents(result, expected) - assert result.name == "new_name" - def test_is_mixed_deprecated(self): # GH#32922 index = self.create_index() @@ -925,7 +807,7 @@ def test_is_all_dates(self, index, expected): assert index.is_all_dates is expected def test_summary(self, index): - self._check_method_works(Index._summary, index) + index._summary() def test_summary_bug(self): # GH3869` @@ -988,9 +870,6 @@ def test_logical_compat(self, op): index = self.create_index() assert getattr(index, op)() == getattr(index.values, op)() - def _check_method_works(self, method, index): - method(index) - @pytest.mark.parametrize("index", ["string", "int", "float"], indirect=True) def test_drop_by_str_label(self, index): n = len(index) diff --git a/pandas/tests/indexes/test_setops.py b/pandas/tests/indexes/test_setops.py index 9d216fda7c19a..b2bab2e720146 100644 --- a/pandas/tests/indexes/test_setops.py +++ b/pandas/tests/indexes/test_setops.py @@ -3,6 +3,7 @@ set operations. """ from datetime import datetime +import operator import numpy as np import pytest @@ -19,6 +20,7 @@ RangeIndex, Series, TimedeltaIndex, + Timestamp, UInt64Index, ) import pandas._testing as tm @@ -589,7 +591,7 @@ def test_union(self, index, sort): @pytest.mark.parametrize("klass", [np.array, Series, list]) @pytest.mark.parametrize("index", ["string"], indirect=True) def test_union_from_iterables(self, index, klass, sort): - # GH 10149 + # GH#10149 first = index[5:20] second = index[:10] everything = index[:20] @@ -615,3 +617,120 @@ def test_union_identity(self, index, sort): union = Index([]).union(first, sort=sort) assert (union is first) is (not sort) + + @pytest.mark.parametrize("index", ["string"], indirect=True) + @pytest.mark.parametrize("second_name,expected", [(None, None), ("name", "name")]) + def test_difference_name_preservation(self, index, second_name, expected, sort): + first = index[5:20] + second = index[:10] + answer = index[10:20] + + first.name = "name" + second.name = second_name + result = first.difference(second, sort=sort) + + assert tm.equalContents(result, answer) + + if expected is None: + assert result.name is None + else: + assert result.name == expected + + def test_difference_empty_arg(self, index, sort): + first = index[5:20] + first.name = "name" + result = first.difference([], sort) + + tm.assert_index_equal(result, first) + + @pytest.mark.parametrize("index", ["string"], indirect=True) + def test_difference_identity(self, index, sort): + first = index[5:20] + first.name = "name" + result = first.difference(first, sort) + + assert len(result) == 0 + assert result.name == first.name + + @pytest.mark.parametrize("index", ["string"], indirect=True) + def test_difference_sort(self, index, sort): + first = index[5:20] + second = index[:10] + + result = first.difference(second, sort) + expected = index[10:20] + + if sort is None: + expected = expected.sort_values() + + tm.assert_index_equal(result, expected) + + @pytest.mark.parametrize("opname", ["difference", "symmetric_difference"]) + def test_difference_incomparable(self, opname): + a = Index([3, Timestamp("2000"), 1]) + b = Index([2, Timestamp("1999"), 1]) + op = operator.methodcaller(opname, b) + + with tm.assert_produces_warning(RuntimeWarning): + # sort=None, the default + result = op(a) + expected = Index([3, Timestamp("2000"), 2, Timestamp("1999")]) + if opname == "difference": + expected = expected[:2] + tm.assert_index_equal(result, expected) + + # sort=False + op = operator.methodcaller(opname, b, sort=False) + result = op(a) + tm.assert_index_equal(result, expected) + + @pytest.mark.xfail(reason="Not implemented") + @pytest.mark.parametrize("opname", ["difference", "symmetric_difference"]) + def test_difference_incomparable_true(self, opname): + # TODO: decide on True behaviour + # # sort=True, raises + a = Index([3, Timestamp("2000"), 1]) + b = Index([2, Timestamp("1999"), 1]) + op = operator.methodcaller(opname, b, sort=True) + + with pytest.raises(TypeError, match="Cannot compare"): + op(a) + + def test_symmetric_difference_mi(self, sort): + index1 = MultiIndex.from_tuples(zip(["foo", "bar", "baz"], [1, 2, 3])) + index2 = MultiIndex.from_tuples([("foo", 1), ("bar", 3)]) + result = index1.symmetric_difference(index2, sort=sort) + expected = MultiIndex.from_tuples([("bar", 2), ("baz", 3), ("bar", 3)]) + if sort is None: + expected = expected.sort_values() + tm.assert_index_equal(result, expected) + assert tm.equalContents(result, expected) + + @pytest.mark.parametrize( + "index2,expected", + [ + (Index([0, 1, np.nan]), Index([2.0, 3.0, 0.0])), + (Index([0, 1]), Index([np.nan, 2.0, 3.0, 0.0])), + ], + ) + def test_symmetric_difference_missing(self, index2, expected, sort): + # GH#13514 change: {nan} - {nan} == {} + # (GH#6444, sorting of nans, is no longer an issue) + index1 = Index([1, np.nan, 2, 3]) + + result = index1.symmetric_difference(index2, sort=sort) + if sort is None: + expected = expected.sort_values() + tm.assert_index_equal(result, expected) + + def test_symmetric_difference_non_index(self, sort): + index1 = Index([1, 2, 3, 4], name="index1") + index2 = np.array([2, 3, 4, 5]) + expected = Index([1, 5]) + result = index1.symmetric_difference(index2, sort=sort) + assert tm.equalContents(result, expected) + assert result.name == "index1" + + result = index1.symmetric_difference(index2, result_name="new_name", sort=sort) + assert tm.equalContents(result, expected) + assert result.name == "new_name" From d5178a9c671627c544e0dfb23ced3b281cb9418e Mon Sep 17 00:00:00 2001 From: Brock Date: Wed, 17 Feb 2021 14:19:15 -0800 Subject: [PATCH 5/5] collect tests by method --- .../tests/indexes/period/test_constructors.py | 21 +++++++++++++++++++ pandas/tests/indexes/period/test_period.py | 19 ----------------- 2 files changed, 21 insertions(+), 19 deletions(-) diff --git a/pandas/tests/indexes/period/test_constructors.py b/pandas/tests/indexes/period/test_constructors.py index c5018bd0e66d2..54e61b35eb70f 100644 --- a/pandas/tests/indexes/period/test_constructors.py +++ b/pandas/tests/indexes/period/test_constructors.py @@ -512,6 +512,27 @@ def test_map_with_string_constructor(self): tm.assert_index_equal(res, expected) +class TestShallowCopy: + def test_shallow_copy_empty(self): + # GH#13067 + idx = PeriodIndex([], freq="M") + result = idx._view() + expected = idx + + tm.assert_index_equal(result, expected) + + def test_shallow_copy_disallow_i8(self): + # GH#24391 + pi = period_range("2018-01-01", periods=3, freq="2D") + with pytest.raises(AssertionError, match="ndarray"): + pi._shallow_copy(pi.asi8) + + def test_shallow_copy_requires_disallow_period_index(self): + pi = period_range("2018-01-01", periods=3, freq="2D") + with pytest.raises(AssertionError, match="PeriodIndex"): + pi._shallow_copy(pi) + + class TestSeriesPeriod: def setup_method(self, method): self.series = Series(period_range("2000-01-01", periods=10, freq="D")) diff --git a/pandas/tests/indexes/period/test_period.py b/pandas/tests/indexes/period/test_period.py index 8574357f53b89..aabc837e25b4b 100644 --- a/pandas/tests/indexes/period/test_period.py +++ b/pandas/tests/indexes/period/test_period.py @@ -79,25 +79,6 @@ def test_make_time_series(self): series = Series(1, index=index) assert isinstance(series, Series) - def test_shallow_copy_empty(self): - # GH13067 - idx = PeriodIndex([], freq="M") - result = idx._view() - expected = idx - - tm.assert_index_equal(result, expected) - - def test_shallow_copy_disallow_i8(self): - # GH-24391 - pi = period_range("2018-01-01", periods=3, freq="2D") - with pytest.raises(AssertionError, match="ndarray"): - pi._shallow_copy(pi.asi8) - - def test_shallow_copy_requires_disallow_period_index(self): - pi = period_range("2018-01-01", periods=3, freq="2D") - with pytest.raises(AssertionError, match="PeriodIndex"): - pi._shallow_copy(pi) - def test_view_asi8(self): idx = PeriodIndex([], freq="M")