diff --git a/pandas/tests/indexes/categorical/test_category.py b/pandas/tests/indexes/categorical/test_category.py index b2b3f76824b9e..2e03c00638a5c 100644 --- a/pandas/tests/indexes/categorical/test_category.py +++ b/pandas/tests/indexes/categorical/test_category.py @@ -28,81 +28,6 @@ def test_can_hold_identifiers(self): key = idx[0] assert idx._can_hold_identifiers_and_holds_name(key) is True - @pytest.mark.parametrize( - "func,op_name", - [ - (lambda idx: idx - idx, "__sub__"), - (lambda idx: idx + idx, "__add__"), - (lambda idx: idx - ["a", "b"], "__sub__"), - (lambda idx: idx + ["a", "b"], "__add__"), - (lambda idx: ["a", "b"] - idx, "__rsub__"), - (lambda idx: ["a", "b"] + idx, "__radd__"), - ], - ) - def test_disallow_addsub_ops(self, func, op_name): - # GH 10039 - # set ops (+/-) raise TypeError - idx = Index(Categorical(["a", "b"])) - cat_or_list = "'(Categorical|list)' and '(Categorical|list)'" - msg = "|".join( - [ - f"cannot perform {op_name} with this index type: CategoricalIndex", - "can only concatenate list", - rf"unsupported operand type\(s\) for [\+-]: {cat_or_list}", - ] - ) - with pytest.raises(TypeError, match=msg): - func(idx) - - def test_method_delegation(self): - - ci = CategoricalIndex(list("aabbca"), categories=list("cabdef")) - result = ci.set_categories(list("cab")) - tm.assert_index_equal( - result, CategoricalIndex(list("aabbca"), categories=list("cab")) - ) - - ci = CategoricalIndex(list("aabbca"), categories=list("cab")) - result = ci.rename_categories(list("efg")) - tm.assert_index_equal( - result, CategoricalIndex(list("ffggef"), categories=list("efg")) - ) - - # GH18862 (let rename_categories take callables) - result = ci.rename_categories(lambda x: x.upper()) - tm.assert_index_equal( - result, CategoricalIndex(list("AABBCA"), categories=list("CAB")) - ) - - ci = CategoricalIndex(list("aabbca"), categories=list("cab")) - result = ci.add_categories(["d"]) - tm.assert_index_equal( - result, CategoricalIndex(list("aabbca"), categories=list("cabd")) - ) - - ci = CategoricalIndex(list("aabbca"), categories=list("cab")) - result = ci.remove_categories(["c"]) - tm.assert_index_equal( - result, - CategoricalIndex(list("aabb") + [np.nan] + ["a"], categories=list("ab")), - ) - - ci = CategoricalIndex(list("aabbca"), categories=list("cabdef")) - result = ci.as_unordered() - tm.assert_index_equal(result, ci) - - ci = CategoricalIndex(list("aabbca"), categories=list("cabdef")) - result = ci.as_ordered() - tm.assert_index_equal( - result, - CategoricalIndex(list("aabbca"), categories=list("cabdef"), ordered=True), - ) - - # invalid - msg = "cannot use inplace with CategoricalIndex" - with pytest.raises(ValueError, match=msg): - ci.set_categories(list("cab"), inplace=True) - def test_append(self): ci = self.create_index() @@ -387,6 +312,24 @@ def test_frame_repr(self): expected = " A\na 1\nb 2\nc 3" assert result == expected + def test_reindex_base(self): + # See test_reindex.py + pass + + def test_map_str(self): + # See test_map.py + pass + + +class TestCategoricalIndex2: + # Tests that are not overriding a test in Base + + def test_format_different_scalar_lengths(self): + # GH35439 + idx = CategoricalIndex(["aaaaaaaaa", "b"]) + expected = ["aaaaaaaaa", "b"] + assert idx.format() == expected + @pytest.mark.parametrize( "dtype, engine_type", [ @@ -410,16 +353,77 @@ def test_engine_type(self, dtype, engine_type): assert np.issubdtype(ci.codes.dtype, dtype) assert isinstance(ci._engine, engine_type) - def test_reindex_base(self): - # See test_reindex.py - pass + @pytest.mark.parametrize( + "func,op_name", + [ + (lambda idx: idx - idx, "__sub__"), + (lambda idx: idx + idx, "__add__"), + (lambda idx: idx - ["a", "b"], "__sub__"), + (lambda idx: idx + ["a", "b"], "__add__"), + (lambda idx: ["a", "b"] - idx, "__rsub__"), + (lambda idx: ["a", "b"] + idx, "__radd__"), + ], + ) + def test_disallow_addsub_ops(self, func, op_name): + # GH 10039 + # set ops (+/-) raise TypeError + idx = Index(Categorical(["a", "b"])) + cat_or_list = "'(Categorical|list)' and '(Categorical|list)'" + msg = "|".join( + [ + f"cannot perform {op_name} with this index type: CategoricalIndex", + "can only concatenate list", + rf"unsupported operand type\(s\) for [\+-]: {cat_or_list}", + ] + ) + with pytest.raises(TypeError, match=msg): + func(idx) - def test_map_str(self): - # See test_map.py - pass + def test_method_delegation(self): - def test_format_different_scalar_lengths(self): - # GH35439 - idx = CategoricalIndex(["aaaaaaaaa", "b"]) - expected = ["aaaaaaaaa", "b"] - assert idx.format() == expected + ci = CategoricalIndex(list("aabbca"), categories=list("cabdef")) + result = ci.set_categories(list("cab")) + tm.assert_index_equal( + result, CategoricalIndex(list("aabbca"), categories=list("cab")) + ) + + ci = CategoricalIndex(list("aabbca"), categories=list("cab")) + result = ci.rename_categories(list("efg")) + tm.assert_index_equal( + result, CategoricalIndex(list("ffggef"), categories=list("efg")) + ) + + # GH18862 (let rename_categories take callables) + result = ci.rename_categories(lambda x: x.upper()) + tm.assert_index_equal( + result, CategoricalIndex(list("AABBCA"), categories=list("CAB")) + ) + + ci = CategoricalIndex(list("aabbca"), categories=list("cab")) + result = ci.add_categories(["d"]) + tm.assert_index_equal( + result, CategoricalIndex(list("aabbca"), categories=list("cabd")) + ) + + ci = CategoricalIndex(list("aabbca"), categories=list("cab")) + result = ci.remove_categories(["c"]) + tm.assert_index_equal( + result, + CategoricalIndex(list("aabb") + [np.nan] + ["a"], categories=list("ab")), + ) + + ci = CategoricalIndex(list("aabbca"), categories=list("cabdef")) + result = ci.as_unordered() + tm.assert_index_equal(result, ci) + + ci = CategoricalIndex(list("aabbca"), categories=list("cabdef")) + result = ci.as_ordered() + tm.assert_index_equal( + result, + CategoricalIndex(list("aabbca"), categories=list("cabdef"), ordered=True), + ) + + # invalid + msg = "cannot use inplace with CategoricalIndex" + with pytest.raises(ValueError, match=msg): + ci.set_categories(list("cab"), inplace=True) diff --git a/pandas/tests/indexes/interval/test_astype.py b/pandas/tests/indexes/interval/test_astype.py index 7bf1ea7355b61..b4af1cb5859f0 100644 --- a/pandas/tests/indexes/interval/test_astype.py +++ b/pandas/tests/indexes/interval/test_astype.py @@ -15,7 +15,7 @@ import pandas._testing as tm -class Base: +class AstypeTests: """Tests common to IntervalIndex with any subtype""" def test_astype_idempotent(self, index): @@ -72,7 +72,7 @@ def test_astype_invalid_dtype(self, index): index.astype("fake_dtype") -class TestIntSubtype(Base): +class TestIntSubtype(AstypeTests): """Tests specific to IntervalIndex with integer-like subtype""" indexes = [ @@ -124,7 +124,7 @@ def test_subtype_integer_errors(self): index.astype(dtype) -class TestFloatSubtype(Base): +class TestFloatSubtype(AstypeTests): """Tests specific to IntervalIndex with float subtype""" indexes = [ @@ -179,7 +179,7 @@ def test_subtype_datetimelike(self, index, subtype): index.astype(dtype) -class TestDatetimelikeSubtype(Base): +class TestDatetimelikeSubtype(AstypeTests): """Tests specific to IntervalIndex with datetime-like subtype""" indexes = [ diff --git a/pandas/tests/indexes/interval/test_base.py b/pandas/tests/indexes/interval/test_base.py index cc782a6e3bb81..738f0be2dbc86 100644 --- a/pandas/tests/indexes/interval/test_base.py +++ b/pandas/tests/indexes/interval/test_base.py @@ -52,6 +52,15 @@ def test_where(self, closed, klass): result = idx.where(klass(cond)) tm.assert_index_equal(result, expected) + def test_getitem_2d_deprecated(self): + # GH#30588 multi-dim indexing is deprecated, but raising is also acceptable + idx = self.create_index() + with pytest.raises(ValueError, match="multi-dimensional indexing not allowed"): + with tm.assert_produces_warning(FutureWarning, check_stacklevel=False): + idx[:, None] + + +class TestPutmask: @pytest.mark.parametrize("tz", ["US/Pacific", None]) def test_putmask_dt64(self, tz): # GH#37968 @@ -75,10 +84,3 @@ def test_putmask_td64(self): result = idx.putmask(mask, idx[-1]) expected = IntervalIndex([idx[-1]] * 3 + list(idx[3:])) tm.assert_index_equal(result, expected) - - def test_getitem_2d_deprecated(self): - # GH#30588 multi-dim indexing is deprecated, but raising is also acceptable - idx = self.create_index() - with pytest.raises(ValueError, match="multi-dimensional indexing not allowed"): - with tm.assert_produces_warning(FutureWarning, check_stacklevel=False): - idx[:, None] diff --git a/pandas/tests/indexes/interval/test_constructors.py b/pandas/tests/indexes/interval/test_constructors.py index 82933a90d976e..8b4cafc17a202 100644 --- a/pandas/tests/indexes/interval/test_constructors.py +++ b/pandas/tests/indexes/interval/test_constructors.py @@ -29,7 +29,7 @@ def name(request): return request.param -class Base: +class ConstructorTests: """ Common tests for all variations of IntervalIndex construction. Input data to be supplied in breaks format, then converted by the subclass method @@ -182,7 +182,7 @@ def test_generic_errors(self, constructor): constructor(**decreasing_kwargs) -class TestFromArrays(Base): +class TestFromArrays(ConstructorTests): """Tests specific to IntervalIndex.from_arrays""" @pytest.fixture @@ -231,7 +231,7 @@ def test_mixed_float_int(self, left_subtype, right_subtype): assert result.dtype.subtype == expected_subtype -class TestFromBreaks(Base): +class TestFromBreaks(ConstructorTests): """Tests specific to IntervalIndex.from_breaks""" @pytest.fixture @@ -269,7 +269,7 @@ def test_left_right_dont_share_data(self): assert result._left.base is None or result._left.base is not result._right.base -class TestFromTuples(Base): +class TestFromTuples(ConstructorTests): """Tests specific to IntervalIndex.from_tuples""" @pytest.fixture @@ -316,7 +316,7 @@ def test_na_tuples(self): tm.assert_index_equal(idx_na_tuple, idx_na_element) -class TestClassConstructors(Base): +class TestClassConstructors(ConstructorTests): """Tests specific to the IntervalIndex/Index constructors""" @pytest.fixture( diff --git a/pandas/tests/indexes/ranges/test_range.py b/pandas/tests/indexes/ranges/test_range.py index cd3a0e7b2241c..8c1272a6e971b 100644 --- a/pandas/tests/indexes/ranges/test_range.py +++ b/pandas/tests/indexes/ranges/test_range.py @@ -318,31 +318,6 @@ def test_slice_keep_name(self): idx = RangeIndex(1, 2, name="asdf") assert idx.name == idx[1:].name - def test_explicit_conversions(self): - - # GH 8608 - # add/sub are overridden explicitly for Float/Int Index - idx = RangeIndex(5) - - # float conversions - arr = np.arange(5, dtype="int64") * 3.2 - expected = Float64Index(arr) - fidx = idx * 3.2 - tm.assert_index_equal(fidx, expected) - fidx = 3.2 * idx - tm.assert_index_equal(fidx, expected) - - # interops with numpy arrays - expected = Float64Index(arr) - a = np.zeros(5, dtype="float64") - result = fidx - a - tm.assert_index_equal(result, expected) - - expected = Float64Index(-arr) - a = np.zeros(5, dtype="float64") - result = a - fidx - tm.assert_index_equal(result, expected) - def test_has_duplicates(self, index): assert index.is_unique assert not index.has_duplicates diff --git a/pandas/tests/indexes/test_numeric.py b/pandas/tests/indexes/test_numeric.py index 11f2a9f07a4c2..ff1632e33c0fb 100644 --- a/pandas/tests/indexes/test_numeric.py +++ b/pandas/tests/indexes/test_numeric.py @@ -11,31 +11,18 @@ from pandas.tests.indexes.common import Base -class Numeric(Base): - def test_where(self): - # Tested in numeric.test_indexing - pass - - def test_can_hold_identifiers(self): - idx = self.create_index() - key = idx[0] - assert idx._can_hold_identifiers_and_holds_name(key) is False - - def test_format(self): - # GH35439 - idx = self.create_index() - max_width = max(len(str(x)) for x in idx) - expected = [str(x).ljust(max_width) for x in idx] - assert idx.format() == expected - - def test_numeric_compat(self): - pass # override Base method - - def test_explicit_conversions(self): +class TestArithmetic: + @pytest.mark.parametrize( + "klass", [Float64Index, Int64Index, UInt64Index, RangeIndex] + ) + def test_arithmetic_explicit_conversions(self, klass): # GH 8608 # add/sub are overridden explicitly for Float/Int Index - idx = self._holder(np.arange(5, dtype="int64")) + if klass is RangeIndex: + idx = RangeIndex(5) + else: + idx = klass(np.arange(5, dtype="int64")) # float conversions arr = np.arange(5, dtype="int64") * 3.2 @@ -56,6 +43,8 @@ def test_explicit_conversions(self): result = a - fidx tm.assert_index_equal(result, expected) + +class TestNumericIndex: def test_index_groupby(self): int_idx = Index(range(6)) float_idx = Index(np.arange(0, 0.6, 0.1)) @@ -84,6 +73,27 @@ def test_index_groupby(self): expected = {ex_keys[0]: idx[[0, 5]], ex_keys[1]: idx[[1, 4]]} tm.assert_dict_equal(idx.groupby(to_groupby), expected) + +class Numeric(Base): + def test_where(self): + # Tested in numeric.test_indexing + pass + + def test_can_hold_identifiers(self): + idx = self.create_index() + key = idx[0] + assert idx._can_hold_identifiers_and_holds_name(key) is False + + def test_format(self): + # GH35439 + idx = self.create_index() + max_width = max(len(str(x)) for x in idx) + expected = [str(x).ljust(max_width) for x in idx] + assert idx.format() == expected + + def test_numeric_compat(self): + pass # override Base method + def test_insert_na(self, nulls_fixture): # GH 18295 (test missing) index = self.create_index()