diff --git a/pandas/tests/indexes/base_class/test_reshape.py b/pandas/tests/indexes/base_class/test_reshape.py new file mode 100644 index 0000000000000..61826f2403a4b --- /dev/null +++ b/pandas/tests/indexes/base_class/test_reshape.py @@ -0,0 +1,61 @@ +""" +Tests for ndarray-like method on the base Index class +""" +import pytest + +import pandas as pd +from pandas import Index +import pandas._testing as tm + + +class TestReshape: + def test_repeat(self): + repeats = 2 + index = pd.Index([1, 2, 3]) + expected = pd.Index([1, 1, 2, 2, 3, 3]) + + result = index.repeat(repeats) + tm.assert_index_equal(result, expected) + + def test_insert(self): + + # GH 7256 + # validate neg/pos inserts + result = Index(["b", "c", "d"]) + + # test 0th element + tm.assert_index_equal(Index(["a", "b", "c", "d"]), result.insert(0, "a")) + + # test Nth element that follows Python list behavior + tm.assert_index_equal(Index(["b", "c", "e", "d"]), result.insert(-1, "e")) + + # test loc +/- neq (0, -1) + tm.assert_index_equal(result.insert(1, "z"), result.insert(-2, "z")) + + # test empty + null_index = Index([]) + tm.assert_index_equal(Index(["a"]), null_index.insert(0, "a")) + + @pytest.mark.parametrize( + "pos,expected", + [ + (0, Index(["b", "c", "d"], name="index")), + (-1, Index(["a", "b", "c"], name="index")), + ], + ) + def test_delete(self, pos, expected): + index = Index(["a", "b", "c", "d"], name="index") + result = index.delete(pos) + tm.assert_index_equal(result, expected) + assert result.name == expected.name + + def test_append_multiple(self): + index = Index(["a", "b", "c", "d", "e", "f"]) + + foos = [index[:2], index[2:4], index[4:]] + result = foos[0].append(foos[1:]) + tm.assert_index_equal(result, index) + + # empty + result = index.append([]) + tm.assert_index_equal(result, index) diff --git a/pandas/tests/indexes/base_class/test_setops.py b/pandas/tests/indexes/base_class/test_setops.py index e7d5e21d0ba47..ec3ef8050967c 100644 --- a/pandas/tests/indexes/base_class/test_setops.py +++ b/pandas/tests/indexes/base_class/test_setops.py @@ -1,12 +1,49 @@ import numpy as np import pytest +import pandas as pd from pandas import Index, Series import pandas._testing as tm from pandas.core.algorithms import safe_sort class TestIndexSetOps: + @pytest.mark.parametrize( + "method", ["union", "intersection", "difference", "symmetric_difference"] + ) + def test_setops_disallow_true(self, method): + idx1 = pd.Index(["a", "b"]) + idx2 = pd.Index(["b", "c"]) + + with pytest.raises(ValueError, match="The 'sort' keyword only takes"): + getattr(idx1, method)(idx2, sort=True) + + def test_setops_preserve_object_dtype(self): + idx = pd.Index([1, 2, 3], dtype=object) + result = idx.intersection(idx[1:]) + expected = idx[1:] + tm.assert_index_equal(result, expected) + + # if other is not monotonic increasing, intersection goes through + # a different route + result = idx.intersection(idx[1:][::-1]) + tm.assert_index_equal(result, expected) + + result = idx._union(idx[1:], sort=None) + expected = idx + tm.assert_index_equal(result, expected) + + result = idx.union(idx[1:], sort=None) + tm.assert_index_equal(result, expected) + + # if other is not monotonic increasing, _union goes through + # a different route + result = idx._union(idx[1:][::-1], sort=None) + tm.assert_index_equal(result, expected) + + result = idx.union(idx[1:][::-1], sort=None) + tm.assert_index_equal(result, expected) + def test_union_base(self): index = Index([0, "a", 1, "b", 2, "c"]) first = index[3:] @@ -28,6 +65,32 @@ def test_union_different_type_base(self, klass): assert tm.equalContents(result, index) + def test_union_sort_other_incomparable(self): + # https://github.com/pandas-dev/pandas/issues/24959 + idx = pd.Index([1, pd.Timestamp("2000")]) + # default (sort=None) + with tm.assert_produces_warning(RuntimeWarning): + result = idx.union(idx[:1]) + + tm.assert_index_equal(result, idx) + + # sort=None + with tm.assert_produces_warning(RuntimeWarning): + result = idx.union(idx[:1], sort=None) + tm.assert_index_equal(result, idx) + + # sort=False + result = idx.union(idx[:1], sort=False) + tm.assert_index_equal(result, idx) + + @pytest.mark.xfail(reason="Not implemented") + def test_union_sort_other_incomparable_true(self): + # TODO decide on True behaviour + # sort=True + idx = pd.Index([1, pd.Timestamp("2000")]) + with pytest.raises(TypeError, match=".*"): + idx.union(idx[:1], sort=True) + @pytest.mark.parametrize("sort", [None, False]) def test_intersection_base(self, sort): # (same results for py2 and py3 but sortedness not tested elsewhere) @@ -50,6 +113,16 @@ def test_intersection_different_type_base(self, klass, sort): result = first.intersection(klass(second.values), sort=sort) assert tm.equalContents(result, second) + def test_intersect_nosort(self): + result = pd.Index(["c", "b", "a"]).intersection(["b", "a"]) + expected = pd.Index(["b", "a"]) + tm.assert_index_equal(result, expected) + + def test_intersection_equal_sort(self): + idx = pd.Index(["c", "a", "b"]) + tm.assert_index_equal(idx.intersection(idx, sort=False), idx) + tm.assert_index_equal(idx.intersection(idx, sort=None), idx) + @pytest.mark.parametrize("sort", [None, False]) def test_difference_base(self, sort): # (same results for py2 and py3 but sortedness not tested elsewhere) diff --git a/pandas/tests/indexes/test_any_index.py b/pandas/tests/indexes/test_any_index.py index 0db63f615c4f8..86881b8984228 100644 --- a/pandas/tests/indexes/test_any_index.py +++ b/pandas/tests/indexes/test_any_index.py @@ -7,7 +7,8 @@ def test_sort(indices): - with pytest.raises(TypeError): + msg = "cannot sort an Index object in-place, use sort_values instead" + with pytest.raises(TypeError, match=msg): indices.sort() diff --git a/pandas/tests/indexes/test_base.py b/pandas/tests/indexes/test_base.py index 04af9b09bbf89..df434ff658fd8 100644 --- a/pandas/tests/indexes/test_base.py +++ b/pandas/tests/indexes/test_base.py @@ -14,7 +14,6 @@ from pandas.compat.numpy import np_datetime64_compat from pandas.util._test_decorators import async_mark -from pandas.core.dtypes.common import is_unsigned_integer_dtype from pandas.core.dtypes.generic import ABCIndex import pandas as pd @@ -107,15 +106,6 @@ def test_constructor_copy(self, index): # arr = np.array(5.) # pytest.raises(Exception, arr.view, Index) - @pytest.mark.parametrize("na_value", [None, np.nan]) - @pytest.mark.parametrize("vtype", [list, tuple, iter]) - def test_construction_list_tuples_nan(self, na_value, vtype): - # GH 18505 : valid tuples containing NaN - values = [(1, "two"), (3.0, na_value)] - result = Index(vtype(values)) - expected = MultiIndex.from_tuples(values) - tm.assert_index_equal(result, expected) - @pytest.mark.parametrize("cast_as_obj", [True, False]) @pytest.mark.parametrize( "index", @@ -236,21 +226,6 @@ def __array__(self, dtype=None) -> np.ndarray: result = pd.Index(ArrayLike(array)) tm.assert_index_equal(result, expected) - @pytest.mark.parametrize( - "dtype", - [int, "int64", "int32", "int16", "int8", "uint64", "uint32", "uint16", "uint8"], - ) - def test_constructor_int_dtype_float(self, dtype): - # GH 18400 - if is_unsigned_integer_dtype(dtype): - index_type = UInt64Index - else: - index_type = Int64Index - - expected = index_type([0, 1, 2, 3]) - result = Index([0.0, 1.0, 2.0, 3.0], dtype=dtype) - tm.assert_index_equal(result, expected) - def test_constructor_int_dtype_nan(self): # see gh-15187 data = [np.nan] @@ -370,19 +345,6 @@ def test_constructor_dtypes_to_float64(self, vals): index = Index(vals, dtype=float) assert isinstance(index, Float64Index) - @pytest.mark.parametrize("cast_index", [True, False]) - @pytest.mark.parametrize( - "vals", [[True, False, True], np.array([True, False, True], dtype=bool)] - ) - def test_constructor_dtypes_to_object(self, cast_index, vals): - if cast_index: - index = Index(vals, dtype=bool) - else: - index = Index(vals) - - assert isinstance(index, Index) - assert index.dtype == object - @pytest.mark.parametrize( "vals", [ @@ -587,25 +549,6 @@ def test_equals_object(self): def test_not_equals_object(self, comp): assert not Index(["a", "b", "c"]).equals(comp) - def test_insert(self): - - # GH 7256 - # validate neg/pos inserts - result = Index(["b", "c", "d"]) - - # test 0th element - tm.assert_index_equal(Index(["a", "b", "c", "d"]), result.insert(0, "a")) - - # test Nth element that follows Python list behavior - tm.assert_index_equal(Index(["b", "c", "e", "d"]), result.insert(-1, "e")) - - # test loc +/- neq (0, -1) - tm.assert_index_equal(result.insert(1, "z"), result.insert(-2, "z")) - - # test empty - null_index = Index([]) - tm.assert_index_equal(Index(["a"]), null_index.insert(0, "a")) - def test_insert_missing(self, nulls_fixture): # GH 22295 # test there is no mangling of NA values @@ -613,19 +556,6 @@ def test_insert_missing(self, nulls_fixture): result = Index(list("abc")).insert(1, nulls_fixture) tm.assert_index_equal(result, expected) - @pytest.mark.parametrize( - "pos,expected", - [ - (0, Index(["b", "c", "d"], name="index")), - (-1, Index(["a", "b", "c"], name="index")), - ], - ) - def test_delete(self, pos, expected): - index = Index(["a", "b", "c", "d"], name="index") - result = index.delete(pos) - tm.assert_index_equal(result, expected) - assert result.name == expected.name - def test_delete_raises(self): index = Index(["a", "b", "c", "d"], name="index") msg = "index 5 is out of bounds for axis 0 with size 4" @@ -839,16 +769,6 @@ def test_intersect_str_dates(self, sort): assert len(result) == 0 - def test_intersect_nosort(self): - result = pd.Index(["c", "b", "a"]).intersection(["b", "a"]) - expected = pd.Index(["b", "a"]) - tm.assert_index_equal(result, expected) - - def test_intersection_equal_sort(self): - idx = pd.Index(["c", "a", "b"]) - tm.assert_index_equal(idx.intersection(idx, sort=False), idx) - tm.assert_index_equal(idx.intersection(idx, sort=None), idx) - @pytest.mark.xfail(reason="Not implemented") def test_intersection_equal_sort_true(self): # TODO decide on True behaviour @@ -910,32 +830,6 @@ def test_union_sort_special_true(self, slice_): expected = pd.Index([0, 1, 2]) tm.assert_index_equal(result, expected) - def test_union_sort_other_incomparable(self): - # https://github.com/pandas-dev/pandas/issues/24959 - idx = pd.Index([1, pd.Timestamp("2000")]) - # default (sort=None) - with tm.assert_produces_warning(RuntimeWarning): - result = idx.union(idx[:1]) - - tm.assert_index_equal(result, idx) - - # sort=None - with tm.assert_produces_warning(RuntimeWarning): - result = idx.union(idx[:1], sort=None) - tm.assert_index_equal(result, idx) - - # sort=False - result = idx.union(idx[:1], sort=False) - tm.assert_index_equal(result, idx) - - @pytest.mark.xfail(reason="Not implemented") - def test_union_sort_other_incomparable_true(self): - # TODO decide on True behaviour - # sort=True - idx = pd.Index([1, pd.Timestamp("2000")]) - with pytest.raises(TypeError, match=".*"): - idx.union(idx[:1], sort=True) - @pytest.mark.parametrize("klass", [np.array, Series, list]) @pytest.mark.parametrize("sort", [None, False]) def test_union_from_iterables(self, index, klass, sort): @@ -1008,42 +902,6 @@ def test_union_dt_as_obj(self, sort): tm.assert_contains_all(index, second_cat) tm.assert_contains_all(date_index, first_cat) - @pytest.mark.parametrize( - "method", ["union", "intersection", "difference", "symmetric_difference"] - ) - def test_setops_disallow_true(self, method): - idx1 = pd.Index(["a", "b"]) - idx2 = pd.Index(["b", "c"]) - - with pytest.raises(ValueError, match="The 'sort' keyword only takes"): - getattr(idx1, method)(idx2, sort=True) - - def test_setops_preserve_object_dtype(self): - idx = pd.Index([1, 2, 3], dtype=object) - result = idx.intersection(idx[1:]) - expected = idx[1:] - tm.assert_index_equal(result, expected) - - # if other is not monotonic increasing, intersection goes through - # a different route - result = idx.intersection(idx[1:][::-1]) - tm.assert_index_equal(result, expected) - - result = idx._union(idx[1:], sort=None) - expected = idx - tm.assert_index_equal(result, expected) - - result = idx.union(idx[1:], sort=None) - tm.assert_index_equal(result, expected) - - # if other is not monotonic increasing, _union goes through - # a different route - result = idx._union(idx[1:][::-1], sort=None) - tm.assert_index_equal(result, expected) - - result = idx.union(idx[1:][::-1], sort=None) - tm.assert_index_equal(result, expected) - def test_map_identity_mapping(self, indices): # GH 12766 tm.assert_index_equal(indices, indices.map(lambda x: x)) @@ -1151,17 +1009,6 @@ def test_map_defaultdict(self): expected = Index(["stuff", "blank", "blank"]) tm.assert_index_equal(result, expected) - def test_append_multiple(self): - index = Index(["a", "b", "c", "d", "e", "f"]) - - foos = [index[:2], index[2:4], index[4:]] - result = foos[0].append(foos[1:]) - tm.assert_index_equal(result, index) - - # empty - result = index.append([]) - tm.assert_index_equal(result, index) - @pytest.mark.parametrize("name,expected", [("foo", "foo"), ("bar", None)]) def test_append_empty_preserve_name(self, name, expected): left = Index([], name="foo") @@ -2437,7 +2284,6 @@ class TestMixedIntIndex(Base): # Mostly the tests from common.py for which the results differ # in py2 and py3 because ints and strings are uncomparable in py3 # (GH 13514) - _holder = Index @pytest.fixture(params=[[0, "a", 1, "b", 2, "c"]], ids=["mixedIndex"]) @@ -2573,14 +2419,6 @@ def test_get_combined_index(self): expected = Index([]) tm.assert_index_equal(result, expected) - def test_repeat(self): - repeats = 2 - index = pd.Index([1, 2, 3]) - expected = pd.Index([1, 1, 2, 2, 3, 3]) - - result = index.repeat(repeats) - tm.assert_index_equal(result, expected) - @pytest.mark.parametrize( "index", [ diff --git a/pandas/tests/indexes/test_common.py b/pandas/tests/indexes/test_common.py index 7e30233353553..b46e6514b4536 100644 --- a/pandas/tests/indexes/test_common.py +++ b/pandas/tests/indexes/test_common.py @@ -158,13 +158,6 @@ def test_set_name_methods(self, indices): assert indices.name == name assert indices.names == [name] - def test_hash_error(self, indices): - index = indices - with pytest.raises( - TypeError, match=f"unhashable type: '{type(index).__name__}'" - ): - hash(indices) - def test_copy_and_deepcopy(self, indices): from copy import copy, deepcopy @@ -246,11 +239,6 @@ def test_get_unique_index(self, indices): result = i._get_unique_index(dropna=dropna) tm.assert_index_equal(result, expected) - def test_sort(self, indices): - msg = "cannot sort an Index object in-place, use sort_values instead" - with pytest.raises(TypeError, match=msg): - indices.sort() - def test_mutability(self, indices): if not len(indices): pytest.skip("Skip check for empty Index") @@ -261,9 +249,6 @@ def test_mutability(self, indices): def test_view(self, indices): assert indices.view().name == indices.name - def test_compat(self, indices): - assert indices.tolist() == list(indices) - def test_searchsorted_monotonic(self, indices): # GH17271 # not implemented for tuple searches in MultiIndex diff --git a/pandas/tests/indexes/test_index_new.py b/pandas/tests/indexes/test_index_new.py new file mode 100644 index 0000000000000..e150df971da2d --- /dev/null +++ b/pandas/tests/indexes/test_index_new.py @@ -0,0 +1,49 @@ +""" +Tests for the Index constructor conducting inference. +""" +import numpy as np +import pytest + +from pandas.core.dtypes.common import is_unsigned_integer_dtype + +from pandas import Index, Int64Index, MultiIndex, UInt64Index +import pandas._testing as tm + + +class TestIndexConstructorInference: + @pytest.mark.parametrize("na_value", [None, np.nan]) + @pytest.mark.parametrize("vtype", [list, tuple, iter]) + def test_construction_list_tuples_nan(self, na_value, vtype): + # GH#18505 : valid tuples containing NaN + values = [(1, "two"), (3.0, na_value)] + result = Index(vtype(values)) + expected = MultiIndex.from_tuples(values) + tm.assert_index_equal(result, expected) + + @pytest.mark.parametrize( + "dtype", + [int, "int64", "int32", "int16", "int8", "uint64", "uint32", "uint16", "uint8"], + ) + def test_constructor_int_dtype_float(self, dtype): + # GH#18400 + if is_unsigned_integer_dtype(dtype): + index_type = UInt64Index + else: + index_type = Int64Index + + expected = index_type([0, 1, 2, 3]) + result = Index([0.0, 1.0, 2.0, 3.0], dtype=dtype) + tm.assert_index_equal(result, expected) + + @pytest.mark.parametrize("cast_index", [True, False]) + @pytest.mark.parametrize( + "vals", [[True, False, True], np.array([True, False, True], dtype=bool)] + ) + def test_constructor_dtypes_to_object(self, cast_index, vals): + if cast_index: + index = Index(vals, dtype=bool) + else: + index = Index(vals) + + assert type(index) is Index + assert index.dtype == object