done
This commit is contained in:
		| @ -0,0 +1,95 @@ | ||||
| import numpy as np | ||||
| import pytest | ||||
|  | ||||
| from pandas import ( | ||||
|     Index, | ||||
|     to_datetime, | ||||
|     to_timedelta, | ||||
| ) | ||||
| import pandas._testing as tm | ||||
|  | ||||
|  | ||||
| class TestAstype: | ||||
|     def test_astype_float64_to_uint64(self): | ||||
|         # GH#45309 used to incorrectly return Index with int64 dtype | ||||
|         idx = Index([0.0, 5.0, 10.0, 15.0, 20.0], dtype=np.float64) | ||||
|         result = idx.astype("u8") | ||||
|         expected = Index([0, 5, 10, 15, 20], dtype=np.uint64) | ||||
|         tm.assert_index_equal(result, expected, exact=True) | ||||
|  | ||||
|         idx_with_negatives = idx - 10 | ||||
|         with pytest.raises(ValueError, match="losslessly"): | ||||
|             idx_with_negatives.astype(np.uint64) | ||||
|  | ||||
|     def test_astype_float64_to_object(self): | ||||
|         float_index = Index([0.0, 2.5, 5.0, 7.5, 10.0], dtype=np.float64) | ||||
|         result = float_index.astype(object) | ||||
|         assert result.equals(float_index) | ||||
|         assert float_index.equals(result) | ||||
|         assert isinstance(result, Index) and result.dtype == object | ||||
|  | ||||
|     def test_astype_float64_mixed_to_object(self): | ||||
|         # mixed int-float | ||||
|         idx = Index([1.5, 2, 3, 4, 5], dtype=np.float64) | ||||
|         idx.name = "foo" | ||||
|         result = idx.astype(object) | ||||
|         assert result.equals(idx) | ||||
|         assert idx.equals(result) | ||||
|         assert isinstance(result, Index) and result.dtype == object | ||||
|  | ||||
|     @pytest.mark.parametrize("dtype", ["int16", "int32", "int64"]) | ||||
|     def test_astype_float64_to_int_dtype(self, dtype): | ||||
|         # GH#12881 | ||||
|         # a float astype int | ||||
|         idx = Index([0, 1, 2], dtype=np.float64) | ||||
|         result = idx.astype(dtype) | ||||
|         expected = Index([0, 1, 2], dtype=dtype) | ||||
|         tm.assert_index_equal(result, expected, exact=True) | ||||
|  | ||||
|         idx = Index([0, 1.1, 2], dtype=np.float64) | ||||
|         result = idx.astype(dtype) | ||||
|         expected = Index([0, 1, 2], dtype=dtype) | ||||
|         tm.assert_index_equal(result, expected, exact=True) | ||||
|  | ||||
|     @pytest.mark.parametrize("dtype", ["float32", "float64"]) | ||||
|     def test_astype_float64_to_float_dtype(self, dtype): | ||||
|         # GH#12881 | ||||
|         # a float astype int | ||||
|         idx = Index([0, 1, 2], dtype=np.float64) | ||||
|         result = idx.astype(dtype) | ||||
|         assert isinstance(result, Index) and result.dtype == dtype | ||||
|  | ||||
|     @pytest.mark.parametrize("dtype", ["M8[ns]", "m8[ns]"]) | ||||
|     def test_astype_float_to_datetimelike(self, dtype): | ||||
|         # GH#49660 pre-2.0 Index.astype from floating to M8/m8/Period raised, | ||||
|         #  inconsistent with Series.astype | ||||
|         idx = Index([0, 1.1, 2], dtype=np.float64) | ||||
|  | ||||
|         result = idx.astype(dtype) | ||||
|         if dtype[0] == "M": | ||||
|             expected = to_datetime(idx.values) | ||||
|         else: | ||||
|             expected = to_timedelta(idx.values) | ||||
|         tm.assert_index_equal(result, expected) | ||||
|  | ||||
|         # check that we match Series behavior | ||||
|         result = idx.to_series().set_axis(range(3)).astype(dtype) | ||||
|         expected = expected.to_series().set_axis(range(3)) | ||||
|         tm.assert_series_equal(result, expected) | ||||
|  | ||||
|     @pytest.mark.parametrize("dtype", [int, "int16", "int32", "int64"]) | ||||
|     @pytest.mark.parametrize("non_finite", [np.inf, np.nan]) | ||||
|     def test_cannot_cast_inf_to_int(self, non_finite, dtype): | ||||
|         # GH#13149 | ||||
|         idx = Index([1, 2, non_finite], dtype=np.float64) | ||||
|  | ||||
|         msg = r"Cannot convert non-finite values \(NA or inf\) to integer" | ||||
|         with pytest.raises(ValueError, match=msg): | ||||
|             idx.astype(dtype) | ||||
|  | ||||
|     def test_astype_from_object(self): | ||||
|         index = Index([1.0, np.nan, 0.2], dtype="object") | ||||
|         result = index.astype(float) | ||||
|         expected = Index([1.0, np.nan, 0.2], dtype=np.float64) | ||||
|         assert result.dtype == expected.dtype | ||||
|         tm.assert_index_equal(result, expected) | ||||
| @ -0,0 +1,611 @@ | ||||
| import numpy as np | ||||
| import pytest | ||||
|  | ||||
| from pandas.errors import InvalidIndexError | ||||
|  | ||||
| from pandas import ( | ||||
|     NA, | ||||
|     Index, | ||||
|     RangeIndex, | ||||
|     Series, | ||||
|     Timestamp, | ||||
| ) | ||||
| import pandas._testing as tm | ||||
| from pandas.core.arrays import ( | ||||
|     ArrowExtensionArray, | ||||
|     FloatingArray, | ||||
| ) | ||||
|  | ||||
|  | ||||
| @pytest.fixture | ||||
| def index_large(): | ||||
|     # large values used in Index[uint64] tests where no compat needed with Int64/Float64 | ||||
|     large = [2**63, 2**63 + 10, 2**63 + 15, 2**63 + 20, 2**63 + 25] | ||||
|     return Index(large, dtype=np.uint64) | ||||
|  | ||||
|  | ||||
| class TestGetLoc: | ||||
|     def test_get_loc(self): | ||||
|         index = Index([0, 1, 2]) | ||||
|         assert index.get_loc(1) == 1 | ||||
|  | ||||
|     def test_get_loc_raises_bad_label(self): | ||||
|         index = Index([0, 1, 2]) | ||||
|         with pytest.raises(InvalidIndexError, match=r"\[1, 2\]"): | ||||
|             index.get_loc([1, 2]) | ||||
|  | ||||
|     def test_get_loc_float64(self): | ||||
|         idx = Index([0.0, 1.0, 2.0], dtype=np.float64) | ||||
|  | ||||
|         with pytest.raises(KeyError, match="^'foo'$"): | ||||
|             idx.get_loc("foo") | ||||
|         with pytest.raises(KeyError, match=r"^1\.5$"): | ||||
|             idx.get_loc(1.5) | ||||
|         with pytest.raises(KeyError, match="^True$"): | ||||
|             idx.get_loc(True) | ||||
|         with pytest.raises(KeyError, match="^False$"): | ||||
|             idx.get_loc(False) | ||||
|  | ||||
|     def test_get_loc_na(self): | ||||
|         idx = Index([np.nan, 1, 2], dtype=np.float64) | ||||
|         assert idx.get_loc(1) == 1 | ||||
|         assert idx.get_loc(np.nan) == 0 | ||||
|  | ||||
|         idx = Index([np.nan, 1, np.nan], dtype=np.float64) | ||||
|         assert idx.get_loc(1) == 1 | ||||
|  | ||||
|         # representable by slice [0:2:2] | ||||
|         msg = "'Cannot get left slice bound for non-unique label: nan'" | ||||
|         with pytest.raises(KeyError, match=msg): | ||||
|             idx.slice_locs(np.nan) | ||||
|         # not representable by slice | ||||
|         idx = Index([np.nan, 1, np.nan, np.nan], dtype=np.float64) | ||||
|         assert idx.get_loc(1) == 1 | ||||
|         msg = "'Cannot get left slice bound for non-unique label: nan" | ||||
|         with pytest.raises(KeyError, match=msg): | ||||
|             idx.slice_locs(np.nan) | ||||
|  | ||||
|     def test_get_loc_missing_nan(self): | ||||
|         # GH#8569 | ||||
|         idx = Index([1, 2], dtype=np.float64) | ||||
|         assert idx.get_loc(1) == 0 | ||||
|         with pytest.raises(KeyError, match=r"^3$"): | ||||
|             idx.get_loc(3) | ||||
|         with pytest.raises(KeyError, match="^nan$"): | ||||
|             idx.get_loc(np.nan) | ||||
|         with pytest.raises(InvalidIndexError, match=r"\[nan\]"): | ||||
|             # listlike/non-hashable raises TypeError | ||||
|             idx.get_loc([np.nan]) | ||||
|  | ||||
|     @pytest.mark.parametrize("vals", [[1], [1.0], [Timestamp("2019-12-31")], ["test"]]) | ||||
|     def test_get_loc_float_index_nan_with_method(self, vals): | ||||
|         # GH#39382 | ||||
|         idx = Index(vals) | ||||
|         with pytest.raises(KeyError, match="nan"): | ||||
|             idx.get_loc(np.nan) | ||||
|  | ||||
|     @pytest.mark.parametrize("dtype", ["f8", "i8", "u8"]) | ||||
|     def test_get_loc_numericindex_none_raises(self, dtype): | ||||
|         # case that goes through searchsorted and key is non-comparable to values | ||||
|         arr = np.arange(10**7, dtype=dtype) | ||||
|         idx = Index(arr) | ||||
|         with pytest.raises(KeyError, match="None"): | ||||
|             idx.get_loc(None) | ||||
|  | ||||
|     def test_get_loc_overflows(self): | ||||
|         # unique but non-monotonic goes through IndexEngine.mapping.get_item | ||||
|         idx = Index([0, 2, 1]) | ||||
|  | ||||
|         val = np.iinfo(np.int64).max + 1 | ||||
|  | ||||
|         with pytest.raises(KeyError, match=str(val)): | ||||
|             idx.get_loc(val) | ||||
|         with pytest.raises(KeyError, match=str(val)): | ||||
|             idx._engine.get_loc(val) | ||||
|  | ||||
|  | ||||
| class TestGetIndexer: | ||||
|     def test_get_indexer(self): | ||||
|         index1 = Index([1, 2, 3, 4, 5]) | ||||
|         index2 = Index([2, 4, 6]) | ||||
|  | ||||
|         r1 = index1.get_indexer(index2) | ||||
|         e1 = np.array([1, 3, -1], dtype=np.intp) | ||||
|         tm.assert_almost_equal(r1, e1) | ||||
|  | ||||
|     @pytest.mark.parametrize("reverse", [True, False]) | ||||
|     @pytest.mark.parametrize( | ||||
|         "expected,method", | ||||
|         [ | ||||
|             (np.array([-1, 0, 0, 1, 1], dtype=np.intp), "pad"), | ||||
|             (np.array([-1, 0, 0, 1, 1], dtype=np.intp), "ffill"), | ||||
|             (np.array([0, 0, 1, 1, 2], dtype=np.intp), "backfill"), | ||||
|             (np.array([0, 0, 1, 1, 2], dtype=np.intp), "bfill"), | ||||
|         ], | ||||
|     ) | ||||
|     def test_get_indexer_methods(self, reverse, expected, method): | ||||
|         index1 = Index([1, 2, 3, 4, 5]) | ||||
|         index2 = Index([2, 4, 6]) | ||||
|  | ||||
|         if reverse: | ||||
|             index1 = index1[::-1] | ||||
|             expected = expected[::-1] | ||||
|  | ||||
|         result = index2.get_indexer(index1, method=method) | ||||
|         tm.assert_almost_equal(result, expected) | ||||
|  | ||||
|     def test_get_indexer_invalid(self): | ||||
|         # GH10411 | ||||
|         index = Index(np.arange(10)) | ||||
|  | ||||
|         with pytest.raises(ValueError, match="tolerance argument"): | ||||
|             index.get_indexer([1, 0], tolerance=1) | ||||
|  | ||||
|         with pytest.raises(ValueError, match="limit argument"): | ||||
|             index.get_indexer([1, 0], limit=1) | ||||
|  | ||||
|     @pytest.mark.parametrize( | ||||
|         "method, tolerance, indexer, expected", | ||||
|         [ | ||||
|             ("pad", None, [0, 5, 9], [0, 5, 9]), | ||||
|             ("backfill", None, [0, 5, 9], [0, 5, 9]), | ||||
|             ("nearest", None, [0, 5, 9], [0, 5, 9]), | ||||
|             ("pad", 0, [0, 5, 9], [0, 5, 9]), | ||||
|             ("backfill", 0, [0, 5, 9], [0, 5, 9]), | ||||
|             ("nearest", 0, [0, 5, 9], [0, 5, 9]), | ||||
|             ("pad", None, [0.2, 1.8, 8.5], [0, 1, 8]), | ||||
|             ("backfill", None, [0.2, 1.8, 8.5], [1, 2, 9]), | ||||
|             ("nearest", None, [0.2, 1.8, 8.5], [0, 2, 9]), | ||||
|             ("pad", 1, [0.2, 1.8, 8.5], [0, 1, 8]), | ||||
|             ("backfill", 1, [0.2, 1.8, 8.5], [1, 2, 9]), | ||||
|             ("nearest", 1, [0.2, 1.8, 8.5], [0, 2, 9]), | ||||
|             ("pad", 0.2, [0.2, 1.8, 8.5], [0, -1, -1]), | ||||
|             ("backfill", 0.2, [0.2, 1.8, 8.5], [-1, 2, -1]), | ||||
|             ("nearest", 0.2, [0.2, 1.8, 8.5], [0, 2, -1]), | ||||
|         ], | ||||
|     ) | ||||
|     def test_get_indexer_nearest(self, method, tolerance, indexer, expected): | ||||
|         index = Index(np.arange(10)) | ||||
|  | ||||
|         actual = index.get_indexer(indexer, method=method, tolerance=tolerance) | ||||
|         tm.assert_numpy_array_equal(actual, np.array(expected, dtype=np.intp)) | ||||
|  | ||||
|     @pytest.mark.parametrize("listtype", [list, tuple, Series, np.array]) | ||||
|     @pytest.mark.parametrize( | ||||
|         "tolerance, expected", | ||||
|         list( | ||||
|             zip( | ||||
|                 [[0.3, 0.3, 0.1], [0.2, 0.1, 0.1], [0.1, 0.5, 0.5]], | ||||
|                 [[0, 2, -1], [0, -1, -1], [-1, 2, 9]], | ||||
|             ) | ||||
|         ), | ||||
|     ) | ||||
|     def test_get_indexer_nearest_listlike_tolerance( | ||||
|         self, tolerance, expected, listtype | ||||
|     ): | ||||
|         index = Index(np.arange(10)) | ||||
|  | ||||
|         actual = index.get_indexer( | ||||
|             [0.2, 1.8, 8.5], method="nearest", tolerance=listtype(tolerance) | ||||
|         ) | ||||
|         tm.assert_numpy_array_equal(actual, np.array(expected, dtype=np.intp)) | ||||
|  | ||||
|     def test_get_indexer_nearest_error(self): | ||||
|         index = Index(np.arange(10)) | ||||
|         with pytest.raises(ValueError, match="limit argument"): | ||||
|             index.get_indexer([1, 0], method="nearest", limit=1) | ||||
|  | ||||
|         with pytest.raises(ValueError, match="tolerance size must match"): | ||||
|             index.get_indexer([1, 0], method="nearest", tolerance=[1, 2, 3]) | ||||
|  | ||||
|     @pytest.mark.parametrize( | ||||
|         "method,expected", | ||||
|         [("pad", [8, 7, 0]), ("backfill", [9, 8, 1]), ("nearest", [9, 7, 0])], | ||||
|     ) | ||||
|     def test_get_indexer_nearest_decreasing(self, method, expected): | ||||
|         index = Index(np.arange(10))[::-1] | ||||
|  | ||||
|         actual = index.get_indexer([0, 5, 9], method=method) | ||||
|         tm.assert_numpy_array_equal(actual, np.array([9, 4, 0], dtype=np.intp)) | ||||
|  | ||||
|         actual = index.get_indexer([0.2, 1.8, 8.5], method=method) | ||||
|         tm.assert_numpy_array_equal(actual, np.array(expected, dtype=np.intp)) | ||||
|  | ||||
|     @pytest.mark.parametrize("idx_dtype", ["int64", "float64", "uint64", "range"]) | ||||
|     @pytest.mark.parametrize("method", ["get_indexer", "get_indexer_non_unique"]) | ||||
|     def test_get_indexer_numeric_index_boolean_target(self, method, idx_dtype): | ||||
|         # GH 16877 | ||||
|  | ||||
|         if idx_dtype == "range": | ||||
|             numeric_index = RangeIndex(4) | ||||
|         else: | ||||
|             numeric_index = Index(np.arange(4, dtype=idx_dtype)) | ||||
|  | ||||
|         other = Index([True, False, True]) | ||||
|  | ||||
|         result = getattr(numeric_index, method)(other) | ||||
|         expected = np.array([-1, -1, -1], dtype=np.intp) | ||||
|         if method == "get_indexer": | ||||
|             tm.assert_numpy_array_equal(result, expected) | ||||
|         else: | ||||
|             missing = np.arange(3, dtype=np.intp) | ||||
|             tm.assert_numpy_array_equal(result[0], expected) | ||||
|             tm.assert_numpy_array_equal(result[1], missing) | ||||
|  | ||||
|     @pytest.mark.parametrize("method", ["pad", "backfill", "nearest"]) | ||||
|     def test_get_indexer_with_method_numeric_vs_bool(self, method): | ||||
|         left = Index([1, 2, 3]) | ||||
|         right = Index([True, False]) | ||||
|  | ||||
|         with pytest.raises(TypeError, match="Cannot compare"): | ||||
|             left.get_indexer(right, method=method) | ||||
|  | ||||
|         with pytest.raises(TypeError, match="Cannot compare"): | ||||
|             right.get_indexer(left, method=method) | ||||
|  | ||||
|     def test_get_indexer_numeric_vs_bool(self): | ||||
|         left = Index([1, 2, 3]) | ||||
|         right = Index([True, False]) | ||||
|  | ||||
|         res = left.get_indexer(right) | ||||
|         expected = -1 * np.ones(len(right), dtype=np.intp) | ||||
|         tm.assert_numpy_array_equal(res, expected) | ||||
|  | ||||
|         res = right.get_indexer(left) | ||||
|         expected = -1 * np.ones(len(left), dtype=np.intp) | ||||
|         tm.assert_numpy_array_equal(res, expected) | ||||
|  | ||||
|         res = left.get_indexer_non_unique(right)[0] | ||||
|         expected = -1 * np.ones(len(right), dtype=np.intp) | ||||
|         tm.assert_numpy_array_equal(res, expected) | ||||
|  | ||||
|         res = right.get_indexer_non_unique(left)[0] | ||||
|         expected = -1 * np.ones(len(left), dtype=np.intp) | ||||
|         tm.assert_numpy_array_equal(res, expected) | ||||
|  | ||||
|     def test_get_indexer_float64(self): | ||||
|         idx = Index([0.0, 1.0, 2.0], dtype=np.float64) | ||||
|         tm.assert_numpy_array_equal( | ||||
|             idx.get_indexer(idx), np.array([0, 1, 2], dtype=np.intp) | ||||
|         ) | ||||
|  | ||||
|         target = [-0.1, 0.5, 1.1] | ||||
|         tm.assert_numpy_array_equal( | ||||
|             idx.get_indexer(target, "pad"), np.array([-1, 0, 1], dtype=np.intp) | ||||
|         ) | ||||
|         tm.assert_numpy_array_equal( | ||||
|             idx.get_indexer(target, "backfill"), np.array([0, 1, 2], dtype=np.intp) | ||||
|         ) | ||||
|         tm.assert_numpy_array_equal( | ||||
|             idx.get_indexer(target, "nearest"), np.array([0, 1, 1], dtype=np.intp) | ||||
|         ) | ||||
|  | ||||
|     def test_get_indexer_nan(self): | ||||
|         # GH#7820 | ||||
|         result = Index([1, 2, np.nan], dtype=np.float64).get_indexer([np.nan]) | ||||
|         expected = np.array([2], dtype=np.intp) | ||||
|         tm.assert_numpy_array_equal(result, expected) | ||||
|  | ||||
|     def test_get_indexer_int64(self): | ||||
|         index = Index(range(0, 20, 2), dtype=np.int64) | ||||
|         target = Index(np.arange(10), dtype=np.int64) | ||||
|         indexer = index.get_indexer(target) | ||||
|         expected = np.array([0, -1, 1, -1, 2, -1, 3, -1, 4, -1], dtype=np.intp) | ||||
|         tm.assert_numpy_array_equal(indexer, expected) | ||||
|  | ||||
|         target = Index(np.arange(10), dtype=np.int64) | ||||
|         indexer = index.get_indexer(target, method="pad") | ||||
|         expected = np.array([0, 0, 1, 1, 2, 2, 3, 3, 4, 4], dtype=np.intp) | ||||
|         tm.assert_numpy_array_equal(indexer, expected) | ||||
|  | ||||
|         target = Index(np.arange(10), dtype=np.int64) | ||||
|         indexer = index.get_indexer(target, method="backfill") | ||||
|         expected = np.array([0, 1, 1, 2, 2, 3, 3, 4, 4, 5], dtype=np.intp) | ||||
|         tm.assert_numpy_array_equal(indexer, expected) | ||||
|  | ||||
|     def test_get_indexer_uint64(self, index_large): | ||||
|         target = Index(np.arange(10).astype("uint64") * 5 + 2**63) | ||||
|         indexer = index_large.get_indexer(target) | ||||
|         expected = np.array([0, -1, 1, 2, 3, 4, -1, -1, -1, -1], dtype=np.intp) | ||||
|         tm.assert_numpy_array_equal(indexer, expected) | ||||
|  | ||||
|         target = Index(np.arange(10).astype("uint64") * 5 + 2**63) | ||||
|         indexer = index_large.get_indexer(target, method="pad") | ||||
|         expected = np.array([0, 0, 1, 2, 3, 4, 4, 4, 4, 4], dtype=np.intp) | ||||
|         tm.assert_numpy_array_equal(indexer, expected) | ||||
|  | ||||
|         target = Index(np.arange(10).astype("uint64") * 5 + 2**63) | ||||
|         indexer = index_large.get_indexer(target, method="backfill") | ||||
|         expected = np.array([0, 1, 1, 2, 3, 4, -1, -1, -1, -1], dtype=np.intp) | ||||
|         tm.assert_numpy_array_equal(indexer, expected) | ||||
|  | ||||
|     @pytest.mark.parametrize("val, val2", [(4, 5), (4, 4), (4, NA), (NA, NA)]) | ||||
|     def test_get_loc_masked(self, val, val2, any_numeric_ea_and_arrow_dtype): | ||||
|         # GH#39133 | ||||
|         idx = Index([1, 2, 3, val, val2], dtype=any_numeric_ea_and_arrow_dtype) | ||||
|         result = idx.get_loc(2) | ||||
|         assert result == 1 | ||||
|  | ||||
|         with pytest.raises(KeyError, match="9"): | ||||
|             idx.get_loc(9) | ||||
|  | ||||
|     def test_get_loc_masked_na(self, any_numeric_ea_and_arrow_dtype): | ||||
|         # GH#39133 | ||||
|         idx = Index([1, 2, NA], dtype=any_numeric_ea_and_arrow_dtype) | ||||
|         result = idx.get_loc(NA) | ||||
|         assert result == 2 | ||||
|  | ||||
|         idx = Index([1, 2, NA, NA], dtype=any_numeric_ea_and_arrow_dtype) | ||||
|         result = idx.get_loc(NA) | ||||
|         tm.assert_numpy_array_equal(result, np.array([False, False, True, True])) | ||||
|  | ||||
|         idx = Index([1, 2, 3], dtype=any_numeric_ea_and_arrow_dtype) | ||||
|         with pytest.raises(KeyError, match="NA"): | ||||
|             idx.get_loc(NA) | ||||
|  | ||||
|     def test_get_loc_masked_na_and_nan(self): | ||||
|         # GH#39133 | ||||
|         idx = Index( | ||||
|             FloatingArray( | ||||
|                 np.array([1, 2, 1, np.nan]), mask=np.array([False, False, True, False]) | ||||
|             ) | ||||
|         ) | ||||
|         result = idx.get_loc(NA) | ||||
|         assert result == 2 | ||||
|         result = idx.get_loc(np.nan) | ||||
|         assert result == 3 | ||||
|  | ||||
|         idx = Index( | ||||
|             FloatingArray(np.array([1, 2, 1.0]), mask=np.array([False, False, True])) | ||||
|         ) | ||||
|         result = idx.get_loc(NA) | ||||
|         assert result == 2 | ||||
|         with pytest.raises(KeyError, match="nan"): | ||||
|             idx.get_loc(np.nan) | ||||
|  | ||||
|         idx = Index( | ||||
|             FloatingArray( | ||||
|                 np.array([1, 2, np.nan]), mask=np.array([False, False, False]) | ||||
|             ) | ||||
|         ) | ||||
|         result = idx.get_loc(np.nan) | ||||
|         assert result == 2 | ||||
|         with pytest.raises(KeyError, match="NA"): | ||||
|             idx.get_loc(NA) | ||||
|  | ||||
|     @pytest.mark.parametrize("val", [4, 2]) | ||||
|     def test_get_indexer_masked_na(self, any_numeric_ea_and_arrow_dtype, val): | ||||
|         # GH#39133 | ||||
|         idx = Index([1, 2, NA, 3, val], dtype=any_numeric_ea_and_arrow_dtype) | ||||
|         result = idx.get_indexer_for([1, NA, 5]) | ||||
|         expected = np.array([0, 2, -1]) | ||||
|         tm.assert_numpy_array_equal(result, expected, check_dtype=False) | ||||
|  | ||||
|     @pytest.mark.parametrize("dtype", ["boolean", "bool[pyarrow]"]) | ||||
|     def test_get_indexer_masked_na_boolean(self, dtype): | ||||
|         # GH#39133 | ||||
|         if dtype == "bool[pyarrow]": | ||||
|             pytest.importorskip("pyarrow") | ||||
|         idx = Index([True, False, NA], dtype=dtype) | ||||
|         result = idx.get_loc(False) | ||||
|         assert result == 1 | ||||
|         result = idx.get_loc(NA) | ||||
|         assert result == 2 | ||||
|  | ||||
|     def test_get_indexer_arrow_dictionary_target(self): | ||||
|         pa = pytest.importorskip("pyarrow") | ||||
|         target = Index( | ||||
|             ArrowExtensionArray( | ||||
|                 pa.array([1, 2], type=pa.dictionary(pa.int8(), pa.int8())) | ||||
|             ) | ||||
|         ) | ||||
|         idx = Index([1]) | ||||
|  | ||||
|         result = idx.get_indexer(target) | ||||
|         expected = np.array([0, -1], dtype=np.int64) | ||||
|         tm.assert_numpy_array_equal(result, expected) | ||||
|  | ||||
|         result_1, result_2 = idx.get_indexer_non_unique(target) | ||||
|         expected_1, expected_2 = np.array([0, -1], dtype=np.int64), np.array( | ||||
|             [1], dtype=np.int64 | ||||
|         ) | ||||
|         tm.assert_numpy_array_equal(result_1, expected_1) | ||||
|         tm.assert_numpy_array_equal(result_2, expected_2) | ||||
|  | ||||
|  | ||||
| class TestWhere: | ||||
|     @pytest.mark.parametrize( | ||||
|         "index", | ||||
|         [ | ||||
|             Index(np.arange(5, dtype="float64")), | ||||
|             Index(range(0, 20, 2), dtype=np.int64), | ||||
|             Index(np.arange(5, dtype="uint64")), | ||||
|         ], | ||||
|     ) | ||||
|     def test_where(self, listlike_box, index): | ||||
|         cond = [True] * len(index) | ||||
|         expected = index | ||||
|         result = index.where(listlike_box(cond)) | ||||
|  | ||||
|         cond = [False] + [True] * (len(index) - 1) | ||||
|         expected = Index([index._na_value] + index[1:].tolist(), dtype=np.float64) | ||||
|         result = index.where(listlike_box(cond)) | ||||
|         tm.assert_index_equal(result, expected) | ||||
|  | ||||
|     def test_where_uint64(self): | ||||
|         idx = Index([0, 6, 2], dtype=np.uint64) | ||||
|         mask = np.array([False, True, False]) | ||||
|         other = np.array([1], dtype=np.int64) | ||||
|  | ||||
|         expected = Index([1, 6, 1], dtype=np.uint64) | ||||
|  | ||||
|         result = idx.where(mask, other) | ||||
|         tm.assert_index_equal(result, expected) | ||||
|  | ||||
|         result = idx.putmask(~mask, other) | ||||
|         tm.assert_index_equal(result, expected) | ||||
|  | ||||
|     def test_where_infers_type_instead_of_trying_to_convert_string_to_float(self): | ||||
|         # GH 32413 | ||||
|         index = Index([1, np.nan]) | ||||
|         cond = index.notna() | ||||
|         other = Index(["a", "b"], dtype="string") | ||||
|  | ||||
|         expected = Index([1.0, "b"]) | ||||
|         result = index.where(cond, other) | ||||
|  | ||||
|         tm.assert_index_equal(result, expected) | ||||
|  | ||||
|  | ||||
| class TestTake: | ||||
|     @pytest.mark.parametrize("idx_dtype", [np.float64, np.int64, np.uint64]) | ||||
|     def test_take_preserve_name(self, idx_dtype): | ||||
|         index = Index([1, 2, 3, 4], dtype=idx_dtype, name="foo") | ||||
|         taken = index.take([3, 0, 1]) | ||||
|         assert index.name == taken.name | ||||
|  | ||||
|     def test_take_fill_value_float64(self): | ||||
|         # GH 12631 | ||||
|         idx = Index([1.0, 2.0, 3.0], name="xxx", dtype=np.float64) | ||||
|         result = idx.take(np.array([1, 0, -1])) | ||||
|         expected = Index([2.0, 1.0, 3.0], dtype=np.float64, name="xxx") | ||||
|         tm.assert_index_equal(result, expected) | ||||
|  | ||||
|         # fill_value | ||||
|         result = idx.take(np.array([1, 0, -1]), fill_value=True) | ||||
|         expected = Index([2.0, 1.0, np.nan], dtype=np.float64, name="xxx") | ||||
|         tm.assert_index_equal(result, expected) | ||||
|  | ||||
|         # allow_fill=False | ||||
|         result = idx.take(np.array([1, 0, -1]), allow_fill=False, fill_value=True) | ||||
|         expected = Index([2.0, 1.0, 3.0], dtype=np.float64, name="xxx") | ||||
|         tm.assert_index_equal(result, expected) | ||||
|  | ||||
|         msg = ( | ||||
|             "When allow_fill=True and fill_value is not None, " | ||||
|             "all indices must be >= -1" | ||||
|         ) | ||||
|         with pytest.raises(ValueError, match=msg): | ||||
|             idx.take(np.array([1, 0, -2]), fill_value=True) | ||||
|         with pytest.raises(ValueError, match=msg): | ||||
|             idx.take(np.array([1, 0, -5]), fill_value=True) | ||||
|  | ||||
|         msg = "index -5 is out of bounds for (axis 0 with )?size 3" | ||||
|         with pytest.raises(IndexError, match=msg): | ||||
|             idx.take(np.array([1, -5])) | ||||
|  | ||||
|     @pytest.mark.parametrize("dtype", [np.int64, np.uint64]) | ||||
|     def test_take_fill_value_ints(self, dtype): | ||||
|         # see gh-12631 | ||||
|         idx = Index([1, 2, 3], dtype=dtype, name="xxx") | ||||
|         result = idx.take(np.array([1, 0, -1])) | ||||
|         expected = Index([2, 1, 3], dtype=dtype, name="xxx") | ||||
|         tm.assert_index_equal(result, expected) | ||||
|  | ||||
|         name = type(idx).__name__ | ||||
|         msg = f"Unable to fill values because {name} cannot contain NA" | ||||
|  | ||||
|         # fill_value=True | ||||
|         with pytest.raises(ValueError, match=msg): | ||||
|             idx.take(np.array([1, 0, -1]), fill_value=True) | ||||
|  | ||||
|         # allow_fill=False | ||||
|         result = idx.take(np.array([1, 0, -1]), allow_fill=False, fill_value=True) | ||||
|         expected = Index([2, 1, 3], dtype=dtype, name="xxx") | ||||
|         tm.assert_index_equal(result, expected) | ||||
|  | ||||
|         with pytest.raises(ValueError, match=msg): | ||||
|             idx.take(np.array([1, 0, -2]), fill_value=True) | ||||
|         with pytest.raises(ValueError, match=msg): | ||||
|             idx.take(np.array([1, 0, -5]), fill_value=True) | ||||
|  | ||||
|         msg = "index -5 is out of bounds for (axis 0 with )?size 3" | ||||
|         with pytest.raises(IndexError, match=msg): | ||||
|             idx.take(np.array([1, -5])) | ||||
|  | ||||
|  | ||||
| class TestContains: | ||||
|     @pytest.mark.parametrize("dtype", [np.float64, np.int64, np.uint64]) | ||||
|     def test_contains_none(self, dtype): | ||||
|         # GH#35788 should return False, not raise TypeError | ||||
|         index = Index([0, 1, 2, 3, 4], dtype=dtype) | ||||
|         assert None not in index | ||||
|  | ||||
|     def test_contains_float64_nans(self): | ||||
|         index = Index([1.0, 2.0, np.nan], dtype=np.float64) | ||||
|         assert np.nan in index | ||||
|  | ||||
|     def test_contains_float64_not_nans(self): | ||||
|         index = Index([1.0, 2.0, np.nan], dtype=np.float64) | ||||
|         assert 1.0 in index | ||||
|  | ||||
|  | ||||
| class TestSliceLocs: | ||||
|     @pytest.mark.parametrize("dtype", [int, float]) | ||||
|     def test_slice_locs(self, dtype): | ||||
|         index = Index(np.array([0, 1, 2, 5, 6, 7, 9, 10], dtype=dtype)) | ||||
|         n = len(index) | ||||
|  | ||||
|         assert index.slice_locs(start=2) == (2, n) | ||||
|         assert index.slice_locs(start=3) == (3, n) | ||||
|         assert index.slice_locs(3, 8) == (3, 6) | ||||
|         assert index.slice_locs(5, 10) == (3, n) | ||||
|         assert index.slice_locs(end=8) == (0, 6) | ||||
|         assert index.slice_locs(end=9) == (0, 7) | ||||
|  | ||||
|         # reversed | ||||
|         index2 = index[::-1] | ||||
|         assert index2.slice_locs(8, 2) == (2, 6) | ||||
|         assert index2.slice_locs(7, 3) == (2, 5) | ||||
|  | ||||
|     @pytest.mark.parametrize("dtype", [int, float]) | ||||
|     def test_slice_locs_float_locs(self, dtype): | ||||
|         index = Index(np.array([0, 1, 2, 5, 6, 7, 9, 10], dtype=dtype)) | ||||
|         n = len(index) | ||||
|         assert index.slice_locs(5.0, 10.0) == (3, n) | ||||
|         assert index.slice_locs(4.5, 10.5) == (3, 8) | ||||
|  | ||||
|         index2 = index[::-1] | ||||
|         assert index2.slice_locs(8.5, 1.5) == (2, 6) | ||||
|         assert index2.slice_locs(10.5, -1) == (0, n) | ||||
|  | ||||
|     @pytest.mark.parametrize("dtype", [int, float]) | ||||
|     def test_slice_locs_dup_numeric(self, dtype): | ||||
|         index = Index(np.array([10, 12, 12, 14], dtype=dtype)) | ||||
|         assert index.slice_locs(12, 12) == (1, 3) | ||||
|         assert index.slice_locs(11, 13) == (1, 3) | ||||
|  | ||||
|         index2 = index[::-1] | ||||
|         assert index2.slice_locs(12, 12) == (1, 3) | ||||
|         assert index2.slice_locs(13, 11) == (1, 3) | ||||
|  | ||||
|     def test_slice_locs_na(self): | ||||
|         index = Index([np.nan, 1, 2]) | ||||
|         assert index.slice_locs(1) == (1, 3) | ||||
|         assert index.slice_locs(np.nan) == (0, 3) | ||||
|  | ||||
|         index = Index([0, np.nan, np.nan, 1, 2]) | ||||
|         assert index.slice_locs(np.nan) == (1, 5) | ||||
|  | ||||
|     def test_slice_locs_na_raises(self): | ||||
|         index = Index([np.nan, 1, 2]) | ||||
|         with pytest.raises(KeyError, match=""): | ||||
|             index.slice_locs(start=1.5) | ||||
|  | ||||
|         with pytest.raises(KeyError, match=""): | ||||
|             index.slice_locs(end=1.5) | ||||
|  | ||||
|  | ||||
| class TestGetSliceBounds: | ||||
|     @pytest.mark.parametrize("side, expected", [("left", 4), ("right", 5)]) | ||||
|     def test_get_slice_bounds_within(self, side, expected): | ||||
|         index = Index(range(6)) | ||||
|         result = index.get_slice_bound(4, side=side) | ||||
|         assert result == expected | ||||
|  | ||||
|     @pytest.mark.parametrize("side", ["left", "right"]) | ||||
|     @pytest.mark.parametrize("bound, expected", [(-1, 0), (10, 6)]) | ||||
|     def test_get_slice_bounds_outside(self, side, expected, bound): | ||||
|         index = Index(range(6)) | ||||
|         result = index.get_slice_bound(bound, side=side) | ||||
|         assert result == expected | ||||
| @ -0,0 +1,380 @@ | ||||
| import numpy as np | ||||
| import pytest | ||||
|  | ||||
| import pandas._testing as tm | ||||
| from pandas.core.indexes.api import Index | ||||
|  | ||||
|  | ||||
| class TestJoinInt64Index: | ||||
|     def test_join_non_unique(self): | ||||
|         left = Index([4, 4, 3, 3]) | ||||
|  | ||||
|         joined, lidx, ridx = left.join(left, return_indexers=True) | ||||
|  | ||||
|         exp_joined = Index([4, 4, 4, 4, 3, 3, 3, 3]) | ||||
|         tm.assert_index_equal(joined, exp_joined) | ||||
|  | ||||
|         exp_lidx = np.array([0, 0, 1, 1, 2, 2, 3, 3], dtype=np.intp) | ||||
|         tm.assert_numpy_array_equal(lidx, exp_lidx) | ||||
|  | ||||
|         exp_ridx = np.array([0, 1, 0, 1, 2, 3, 2, 3], dtype=np.intp) | ||||
|         tm.assert_numpy_array_equal(ridx, exp_ridx) | ||||
|  | ||||
|     def test_join_inner(self): | ||||
|         index = Index(range(0, 20, 2), dtype=np.int64) | ||||
|         other = Index([7, 12, 25, 1, 2, 5], dtype=np.int64) | ||||
|         other_mono = Index([1, 2, 5, 7, 12, 25], dtype=np.int64) | ||||
|  | ||||
|         # not monotonic | ||||
|         res, lidx, ridx = index.join(other, how="inner", return_indexers=True) | ||||
|  | ||||
|         # no guarantee of sortedness, so sort for comparison purposes | ||||
|         ind = res.argsort() | ||||
|         res = res.take(ind) | ||||
|         lidx = lidx.take(ind) | ||||
|         ridx = ridx.take(ind) | ||||
|  | ||||
|         eres = Index([2, 12], dtype=np.int64) | ||||
|         elidx = np.array([1, 6], dtype=np.intp) | ||||
|         eridx = np.array([4, 1], dtype=np.intp) | ||||
|  | ||||
|         assert isinstance(res, Index) and res.dtype == np.int64 | ||||
|         tm.assert_index_equal(res, eres) | ||||
|         tm.assert_numpy_array_equal(lidx, elidx) | ||||
|         tm.assert_numpy_array_equal(ridx, eridx) | ||||
|  | ||||
|         # monotonic | ||||
|         res, lidx, ridx = index.join(other_mono, how="inner", return_indexers=True) | ||||
|  | ||||
|         res2 = index.intersection(other_mono) | ||||
|         tm.assert_index_equal(res, res2) | ||||
|  | ||||
|         elidx = np.array([1, 6], dtype=np.intp) | ||||
|         eridx = np.array([1, 4], dtype=np.intp) | ||||
|         assert isinstance(res, Index) and res.dtype == np.int64 | ||||
|         tm.assert_index_equal(res, eres) | ||||
|         tm.assert_numpy_array_equal(lidx, elidx) | ||||
|         tm.assert_numpy_array_equal(ridx, eridx) | ||||
|  | ||||
|     def test_join_left(self): | ||||
|         index = Index(range(0, 20, 2), dtype=np.int64) | ||||
|         other = Index([7, 12, 25, 1, 2, 5], dtype=np.int64) | ||||
|         other_mono = Index([1, 2, 5, 7, 12, 25], dtype=np.int64) | ||||
|  | ||||
|         # not monotonic | ||||
|         res, lidx, ridx = index.join(other, how="left", return_indexers=True) | ||||
|         eres = index | ||||
|         eridx = np.array([-1, 4, -1, -1, -1, -1, 1, -1, -1, -1], dtype=np.intp) | ||||
|  | ||||
|         assert isinstance(res, Index) and res.dtype == np.int64 | ||||
|         tm.assert_index_equal(res, eres) | ||||
|         assert lidx is None | ||||
|         tm.assert_numpy_array_equal(ridx, eridx) | ||||
|  | ||||
|         # monotonic | ||||
|         res, lidx, ridx = index.join(other_mono, how="left", return_indexers=True) | ||||
|         eridx = np.array([-1, 1, -1, -1, -1, -1, 4, -1, -1, -1], dtype=np.intp) | ||||
|         assert isinstance(res, Index) and res.dtype == np.int64 | ||||
|         tm.assert_index_equal(res, eres) | ||||
|         assert lidx is None | ||||
|         tm.assert_numpy_array_equal(ridx, eridx) | ||||
|  | ||||
|         # non-unique | ||||
|         idx = Index([1, 1, 2, 5]) | ||||
|         idx2 = Index([1, 2, 5, 7, 9]) | ||||
|         res, lidx, ridx = idx2.join(idx, how="left", return_indexers=True) | ||||
|         eres = Index([1, 1, 2, 5, 7, 9])  # 1 is in idx2, so it should be x2 | ||||
|         eridx = np.array([0, 1, 2, 3, -1, -1], dtype=np.intp) | ||||
|         elidx = np.array([0, 0, 1, 2, 3, 4], dtype=np.intp) | ||||
|         tm.assert_index_equal(res, eres) | ||||
|         tm.assert_numpy_array_equal(lidx, elidx) | ||||
|         tm.assert_numpy_array_equal(ridx, eridx) | ||||
|  | ||||
|     def test_join_right(self): | ||||
|         index = Index(range(0, 20, 2), dtype=np.int64) | ||||
|         other = Index([7, 12, 25, 1, 2, 5], dtype=np.int64) | ||||
|         other_mono = Index([1, 2, 5, 7, 12, 25], dtype=np.int64) | ||||
|  | ||||
|         # not monotonic | ||||
|         res, lidx, ridx = index.join(other, how="right", return_indexers=True) | ||||
|         eres = other | ||||
|         elidx = np.array([-1, 6, -1, -1, 1, -1], dtype=np.intp) | ||||
|  | ||||
|         assert isinstance(other, Index) and other.dtype == np.int64 | ||||
|         tm.assert_index_equal(res, eres) | ||||
|         tm.assert_numpy_array_equal(lidx, elidx) | ||||
|         assert ridx is None | ||||
|  | ||||
|         # monotonic | ||||
|         res, lidx, ridx = index.join(other_mono, how="right", return_indexers=True) | ||||
|         eres = other_mono | ||||
|         elidx = np.array([-1, 1, -1, -1, 6, -1], dtype=np.intp) | ||||
|         assert isinstance(other, Index) and other.dtype == np.int64 | ||||
|         tm.assert_index_equal(res, eres) | ||||
|         tm.assert_numpy_array_equal(lidx, elidx) | ||||
|         assert ridx is None | ||||
|  | ||||
|         # non-unique | ||||
|         idx = Index([1, 1, 2, 5]) | ||||
|         idx2 = Index([1, 2, 5, 7, 9]) | ||||
|         res, lidx, ridx = idx.join(idx2, how="right", return_indexers=True) | ||||
|         eres = Index([1, 1, 2, 5, 7, 9])  # 1 is in idx2, so it should be x2 | ||||
|         elidx = np.array([0, 1, 2, 3, -1, -1], dtype=np.intp) | ||||
|         eridx = np.array([0, 0, 1, 2, 3, 4], dtype=np.intp) | ||||
|         tm.assert_index_equal(res, eres) | ||||
|         tm.assert_numpy_array_equal(lidx, elidx) | ||||
|         tm.assert_numpy_array_equal(ridx, eridx) | ||||
|  | ||||
|     def test_join_non_int_index(self): | ||||
|         index = Index(range(0, 20, 2), dtype=np.int64) | ||||
|         other = Index([3, 6, 7, 8, 10], dtype=object) | ||||
|  | ||||
|         outer = index.join(other, how="outer") | ||||
|         outer2 = other.join(index, how="outer") | ||||
|         expected = Index([0, 2, 3, 4, 6, 7, 8, 10, 12, 14, 16, 18]) | ||||
|         tm.assert_index_equal(outer, outer2) | ||||
|         tm.assert_index_equal(outer, expected) | ||||
|  | ||||
|         inner = index.join(other, how="inner") | ||||
|         inner2 = other.join(index, how="inner") | ||||
|         expected = Index([6, 8, 10]) | ||||
|         tm.assert_index_equal(inner, inner2) | ||||
|         tm.assert_index_equal(inner, expected) | ||||
|  | ||||
|         left = index.join(other, how="left") | ||||
|         tm.assert_index_equal(left, index.astype(object)) | ||||
|  | ||||
|         left2 = other.join(index, how="left") | ||||
|         tm.assert_index_equal(left2, other) | ||||
|  | ||||
|         right = index.join(other, how="right") | ||||
|         tm.assert_index_equal(right, other) | ||||
|  | ||||
|         right2 = other.join(index, how="right") | ||||
|         tm.assert_index_equal(right2, index.astype(object)) | ||||
|  | ||||
|     def test_join_outer(self): | ||||
|         index = Index(range(0, 20, 2), dtype=np.int64) | ||||
|         other = Index([7, 12, 25, 1, 2, 5], dtype=np.int64) | ||||
|         other_mono = Index([1, 2, 5, 7, 12, 25], dtype=np.int64) | ||||
|  | ||||
|         # not monotonic | ||||
|         # guarantee of sortedness | ||||
|         res, lidx, ridx = index.join(other, how="outer", return_indexers=True) | ||||
|         noidx_res = index.join(other, how="outer") | ||||
|         tm.assert_index_equal(res, noidx_res) | ||||
|  | ||||
|         eres = Index([0, 1, 2, 4, 5, 6, 7, 8, 10, 12, 14, 16, 18, 25], dtype=np.int64) | ||||
|         elidx = np.array([0, -1, 1, 2, -1, 3, -1, 4, 5, 6, 7, 8, 9, -1], dtype=np.intp) | ||||
|         eridx = np.array( | ||||
|             [-1, 3, 4, -1, 5, -1, 0, -1, -1, 1, -1, -1, -1, 2], dtype=np.intp | ||||
|         ) | ||||
|  | ||||
|         assert isinstance(res, Index) and res.dtype == np.int64 | ||||
|         tm.assert_index_equal(res, eres) | ||||
|         tm.assert_numpy_array_equal(lidx, elidx) | ||||
|         tm.assert_numpy_array_equal(ridx, eridx) | ||||
|  | ||||
|         # monotonic | ||||
|         res, lidx, ridx = index.join(other_mono, how="outer", return_indexers=True) | ||||
|         noidx_res = index.join(other_mono, how="outer") | ||||
|         tm.assert_index_equal(res, noidx_res) | ||||
|  | ||||
|         elidx = np.array([0, -1, 1, 2, -1, 3, -1, 4, 5, 6, 7, 8, 9, -1], dtype=np.intp) | ||||
|         eridx = np.array( | ||||
|             [-1, 0, 1, -1, 2, -1, 3, -1, -1, 4, -1, -1, -1, 5], dtype=np.intp | ||||
|         ) | ||||
|         assert isinstance(res, Index) and res.dtype == np.int64 | ||||
|         tm.assert_index_equal(res, eres) | ||||
|         tm.assert_numpy_array_equal(lidx, elidx) | ||||
|         tm.assert_numpy_array_equal(ridx, eridx) | ||||
|  | ||||
|  | ||||
| class TestJoinUInt64Index: | ||||
|     @pytest.fixture | ||||
|     def index_large(self): | ||||
|         # large values used in TestUInt64Index where no compat needed with int64/float64 | ||||
|         large = [2**63, 2**63 + 10, 2**63 + 15, 2**63 + 20, 2**63 + 25] | ||||
|         return Index(large, dtype=np.uint64) | ||||
|  | ||||
|     def test_join_inner(self, index_large): | ||||
|         other = Index(2**63 + np.array([7, 12, 25, 1, 2, 10], dtype="uint64")) | ||||
|         other_mono = Index(2**63 + np.array([1, 2, 7, 10, 12, 25], dtype="uint64")) | ||||
|  | ||||
|         # not monotonic | ||||
|         res, lidx, ridx = index_large.join(other, how="inner", return_indexers=True) | ||||
|  | ||||
|         # no guarantee of sortedness, so sort for comparison purposes | ||||
|         ind = res.argsort() | ||||
|         res = res.take(ind) | ||||
|         lidx = lidx.take(ind) | ||||
|         ridx = ridx.take(ind) | ||||
|  | ||||
|         eres = Index(2**63 + np.array([10, 25], dtype="uint64")) | ||||
|         elidx = np.array([1, 4], dtype=np.intp) | ||||
|         eridx = np.array([5, 2], dtype=np.intp) | ||||
|  | ||||
|         assert isinstance(res, Index) and res.dtype == np.uint64 | ||||
|         tm.assert_index_equal(res, eres) | ||||
|         tm.assert_numpy_array_equal(lidx, elidx) | ||||
|         tm.assert_numpy_array_equal(ridx, eridx) | ||||
|  | ||||
|         # monotonic | ||||
|         res, lidx, ridx = index_large.join( | ||||
|             other_mono, how="inner", return_indexers=True | ||||
|         ) | ||||
|  | ||||
|         res2 = index_large.intersection(other_mono) | ||||
|         tm.assert_index_equal(res, res2) | ||||
|  | ||||
|         elidx = np.array([1, 4], dtype=np.intp) | ||||
|         eridx = np.array([3, 5], dtype=np.intp) | ||||
|  | ||||
|         assert isinstance(res, Index) and res.dtype == np.uint64 | ||||
|         tm.assert_index_equal(res, eres) | ||||
|         tm.assert_numpy_array_equal(lidx, elidx) | ||||
|         tm.assert_numpy_array_equal(ridx, eridx) | ||||
|  | ||||
|     def test_join_left(self, index_large): | ||||
|         other = Index(2**63 + np.array([7, 12, 25, 1, 2, 10], dtype="uint64")) | ||||
|         other_mono = Index(2**63 + np.array([1, 2, 7, 10, 12, 25], dtype="uint64")) | ||||
|  | ||||
|         # not monotonic | ||||
|         res, lidx, ridx = index_large.join(other, how="left", return_indexers=True) | ||||
|         eres = index_large | ||||
|         eridx = np.array([-1, 5, -1, -1, 2], dtype=np.intp) | ||||
|  | ||||
|         assert isinstance(res, Index) and res.dtype == np.uint64 | ||||
|         tm.assert_index_equal(res, eres) | ||||
|         assert lidx is None | ||||
|         tm.assert_numpy_array_equal(ridx, eridx) | ||||
|  | ||||
|         # monotonic | ||||
|         res, lidx, ridx = index_large.join(other_mono, how="left", return_indexers=True) | ||||
|         eridx = np.array([-1, 3, -1, -1, 5], dtype=np.intp) | ||||
|  | ||||
|         assert isinstance(res, Index) and res.dtype == np.uint64 | ||||
|         tm.assert_index_equal(res, eres) | ||||
|         assert lidx is None | ||||
|         tm.assert_numpy_array_equal(ridx, eridx) | ||||
|  | ||||
|         # non-unique | ||||
|         idx = Index(2**63 + np.array([1, 1, 2, 5], dtype="uint64")) | ||||
|         idx2 = Index(2**63 + np.array([1, 2, 5, 7, 9], dtype="uint64")) | ||||
|         res, lidx, ridx = idx2.join(idx, how="left", return_indexers=True) | ||||
|  | ||||
|         # 1 is in idx2, so it should be x2 | ||||
|         eres = Index(2**63 + np.array([1, 1, 2, 5, 7, 9], dtype="uint64")) | ||||
|         eridx = np.array([0, 1, 2, 3, -1, -1], dtype=np.intp) | ||||
|         elidx = np.array([0, 0, 1, 2, 3, 4], dtype=np.intp) | ||||
|  | ||||
|         tm.assert_index_equal(res, eres) | ||||
|         tm.assert_numpy_array_equal(lidx, elidx) | ||||
|         tm.assert_numpy_array_equal(ridx, eridx) | ||||
|  | ||||
|     def test_join_right(self, index_large): | ||||
|         other = Index(2**63 + np.array([7, 12, 25, 1, 2, 10], dtype="uint64")) | ||||
|         other_mono = Index(2**63 + np.array([1, 2, 7, 10, 12, 25], dtype="uint64")) | ||||
|  | ||||
|         # not monotonic | ||||
|         res, lidx, ridx = index_large.join(other, how="right", return_indexers=True) | ||||
|         eres = other | ||||
|         elidx = np.array([-1, -1, 4, -1, -1, 1], dtype=np.intp) | ||||
|  | ||||
|         tm.assert_numpy_array_equal(lidx, elidx) | ||||
|         assert isinstance(other, Index) and other.dtype == np.uint64 | ||||
|         tm.assert_index_equal(res, eres) | ||||
|         assert ridx is None | ||||
|  | ||||
|         # monotonic | ||||
|         res, lidx, ridx = index_large.join( | ||||
|             other_mono, how="right", return_indexers=True | ||||
|         ) | ||||
|         eres = other_mono | ||||
|         elidx = np.array([-1, -1, -1, 1, -1, 4], dtype=np.intp) | ||||
|  | ||||
|         assert isinstance(other, Index) and other.dtype == np.uint64 | ||||
|         tm.assert_numpy_array_equal(lidx, elidx) | ||||
|         tm.assert_index_equal(res, eres) | ||||
|         assert ridx is None | ||||
|  | ||||
|         # non-unique | ||||
|         idx = Index(2**63 + np.array([1, 1, 2, 5], dtype="uint64")) | ||||
|         idx2 = Index(2**63 + np.array([1, 2, 5, 7, 9], dtype="uint64")) | ||||
|         res, lidx, ridx = idx.join(idx2, how="right", return_indexers=True) | ||||
|  | ||||
|         # 1 is in idx2, so it should be x2 | ||||
|         eres = Index(2**63 + np.array([1, 1, 2, 5, 7, 9], dtype="uint64")) | ||||
|         elidx = np.array([0, 1, 2, 3, -1, -1], dtype=np.intp) | ||||
|         eridx = np.array([0, 0, 1, 2, 3, 4], dtype=np.intp) | ||||
|  | ||||
|         tm.assert_index_equal(res, eres) | ||||
|         tm.assert_numpy_array_equal(lidx, elidx) | ||||
|         tm.assert_numpy_array_equal(ridx, eridx) | ||||
|  | ||||
|     def test_join_non_int_index(self, index_large): | ||||
|         other = Index( | ||||
|             2**63 + np.array([1, 5, 7, 10, 20], dtype="uint64"), dtype=object | ||||
|         ) | ||||
|  | ||||
|         outer = index_large.join(other, how="outer") | ||||
|         outer2 = other.join(index_large, how="outer") | ||||
|         expected = Index( | ||||
|             2**63 + np.array([0, 1, 5, 7, 10, 15, 20, 25], dtype="uint64") | ||||
|         ) | ||||
|         tm.assert_index_equal(outer, outer2) | ||||
|         tm.assert_index_equal(outer, expected) | ||||
|  | ||||
|         inner = index_large.join(other, how="inner") | ||||
|         inner2 = other.join(index_large, how="inner") | ||||
|         expected = Index(2**63 + np.array([10, 20], dtype="uint64")) | ||||
|         tm.assert_index_equal(inner, inner2) | ||||
|         tm.assert_index_equal(inner, expected) | ||||
|  | ||||
|         left = index_large.join(other, how="left") | ||||
|         tm.assert_index_equal(left, index_large.astype(object)) | ||||
|  | ||||
|         left2 = other.join(index_large, how="left") | ||||
|         tm.assert_index_equal(left2, other) | ||||
|  | ||||
|         right = index_large.join(other, how="right") | ||||
|         tm.assert_index_equal(right, other) | ||||
|  | ||||
|         right2 = other.join(index_large, how="right") | ||||
|         tm.assert_index_equal(right2, index_large.astype(object)) | ||||
|  | ||||
|     def test_join_outer(self, index_large): | ||||
|         other = Index(2**63 + np.array([7, 12, 25, 1, 2, 10], dtype="uint64")) | ||||
|         other_mono = Index(2**63 + np.array([1, 2, 7, 10, 12, 25], dtype="uint64")) | ||||
|  | ||||
|         # not monotonic | ||||
|         # guarantee of sortedness | ||||
|         res, lidx, ridx = index_large.join(other, how="outer", return_indexers=True) | ||||
|         noidx_res = index_large.join(other, how="outer") | ||||
|         tm.assert_index_equal(res, noidx_res) | ||||
|  | ||||
|         eres = Index( | ||||
|             2**63 + np.array([0, 1, 2, 7, 10, 12, 15, 20, 25], dtype="uint64") | ||||
|         ) | ||||
|         elidx = np.array([0, -1, -1, -1, 1, -1, 2, 3, 4], dtype=np.intp) | ||||
|         eridx = np.array([-1, 3, 4, 0, 5, 1, -1, -1, 2], dtype=np.intp) | ||||
|  | ||||
|         assert isinstance(res, Index) and res.dtype == np.uint64 | ||||
|         tm.assert_index_equal(res, eres) | ||||
|         tm.assert_numpy_array_equal(lidx, elidx) | ||||
|         tm.assert_numpy_array_equal(ridx, eridx) | ||||
|  | ||||
|         # monotonic | ||||
|         res, lidx, ridx = index_large.join( | ||||
|             other_mono, how="outer", return_indexers=True | ||||
|         ) | ||||
|         noidx_res = index_large.join(other_mono, how="outer") | ||||
|         tm.assert_index_equal(res, noidx_res) | ||||
|  | ||||
|         elidx = np.array([0, -1, -1, -1, 1, -1, 2, 3, 4], dtype=np.intp) | ||||
|         eridx = np.array([-1, 0, 1, 2, 3, 4, -1, -1, 5], dtype=np.intp) | ||||
|  | ||||
|         assert isinstance(res, Index) and res.dtype == np.uint64 | ||||
|         tm.assert_index_equal(res, eres) | ||||
|         tm.assert_numpy_array_equal(lidx, elidx) | ||||
|         tm.assert_numpy_array_equal(ridx, eridx) | ||||
| @ -0,0 +1,553 @@ | ||||
| import numpy as np | ||||
| import pytest | ||||
|  | ||||
| import pandas as pd | ||||
| from pandas import ( | ||||
|     Index, | ||||
|     Series, | ||||
| ) | ||||
| import pandas._testing as tm | ||||
|  | ||||
|  | ||||
| class TestFloatNumericIndex: | ||||
|     @pytest.fixture(params=[np.float64, np.float32]) | ||||
|     def dtype(self, request): | ||||
|         return request.param | ||||
|  | ||||
|     @pytest.fixture | ||||
|     def simple_index(self, dtype): | ||||
|         values = np.arange(5, dtype=dtype) | ||||
|         return Index(values) | ||||
|  | ||||
|     @pytest.fixture( | ||||
|         params=[ | ||||
|             [1.5, 2, 3, 4, 5], | ||||
|             [0.0, 2.5, 5.0, 7.5, 10.0], | ||||
|             [5, 4, 3, 2, 1.5], | ||||
|             [10.0, 7.5, 5.0, 2.5, 0.0], | ||||
|         ], | ||||
|         ids=["mixed", "float", "mixed_dec", "float_dec"], | ||||
|     ) | ||||
|     def index(self, request, dtype): | ||||
|         return Index(request.param, dtype=dtype) | ||||
|  | ||||
|     @pytest.fixture | ||||
|     def mixed_index(self, dtype): | ||||
|         return Index([1.5, 2, 3, 4, 5], dtype=dtype) | ||||
|  | ||||
|     @pytest.fixture | ||||
|     def float_index(self, dtype): | ||||
|         return Index([0.0, 2.5, 5.0, 7.5, 10.0], dtype=dtype) | ||||
|  | ||||
|     def test_repr_roundtrip(self, index): | ||||
|         tm.assert_index_equal(eval(repr(index)), index, exact=True) | ||||
|  | ||||
|     def check_coerce(self, a, b, is_float_index=True): | ||||
|         assert a.equals(b) | ||||
|         tm.assert_index_equal(a, b, exact=False) | ||||
|         if is_float_index: | ||||
|             assert isinstance(b, Index) | ||||
|         else: | ||||
|             assert type(b) is Index | ||||
|  | ||||
|     def test_constructor_from_list_no_dtype(self): | ||||
|         index = Index([1.5, 2.5, 3.5]) | ||||
|         assert index.dtype == np.float64 | ||||
|  | ||||
|     def test_constructor(self, dtype): | ||||
|         index_cls = Index | ||||
|  | ||||
|         # explicit construction | ||||
|         index = index_cls([1, 2, 3, 4, 5], dtype=dtype) | ||||
|  | ||||
|         assert isinstance(index, index_cls) | ||||
|         assert index.dtype == dtype | ||||
|  | ||||
|         expected = np.array([1, 2, 3, 4, 5], dtype=dtype) | ||||
|         tm.assert_numpy_array_equal(index.values, expected) | ||||
|  | ||||
|         index = index_cls(np.array([1, 2, 3, 4, 5]), dtype=dtype) | ||||
|         assert isinstance(index, index_cls) | ||||
|         assert index.dtype == dtype | ||||
|  | ||||
|         index = index_cls([1.0, 2, 3, 4, 5], dtype=dtype) | ||||
|         assert isinstance(index, index_cls) | ||||
|         assert index.dtype == dtype | ||||
|  | ||||
|         index = index_cls(np.array([1.0, 2, 3, 4, 5]), dtype=dtype) | ||||
|         assert isinstance(index, index_cls) | ||||
|         assert index.dtype == dtype | ||||
|  | ||||
|         index = index_cls([1.0, 2, 3, 4, 5], dtype=dtype) | ||||
|         assert isinstance(index, index_cls) | ||||
|         assert index.dtype == dtype | ||||
|  | ||||
|         index = index_cls(np.array([1.0, 2, 3, 4, 5]), dtype=dtype) | ||||
|         assert isinstance(index, index_cls) | ||||
|         assert index.dtype == dtype | ||||
|  | ||||
|         # nan handling | ||||
|         result = index_cls([np.nan, np.nan], dtype=dtype) | ||||
|         assert pd.isna(result.values).all() | ||||
|  | ||||
|         result = index_cls(np.array([np.nan]), dtype=dtype) | ||||
|         assert pd.isna(result.values).all() | ||||
|  | ||||
|     def test_constructor_invalid(self): | ||||
|         index_cls = Index | ||||
|         cls_name = index_cls.__name__ | ||||
|         # invalid | ||||
|         msg = ( | ||||
|             rf"{cls_name}\(\.\.\.\) must be called with a collection of " | ||||
|             r"some kind, 0\.0 was passed" | ||||
|         ) | ||||
|         with pytest.raises(TypeError, match=msg): | ||||
|             index_cls(0.0) | ||||
|  | ||||
|     def test_constructor_coerce(self, mixed_index, float_index): | ||||
|         self.check_coerce(mixed_index, Index([1.5, 2, 3, 4, 5])) | ||||
|         self.check_coerce(float_index, Index(np.arange(5) * 2.5)) | ||||
|  | ||||
|         result = Index(np.array(np.arange(5) * 2.5, dtype=object)) | ||||
|         assert result.dtype == object  # as of 2.0 to match Series | ||||
|         self.check_coerce(float_index, result.astype("float64")) | ||||
|  | ||||
|     def test_constructor_explicit(self, mixed_index, float_index): | ||||
|         # these don't auto convert | ||||
|         self.check_coerce( | ||||
|             float_index, Index((np.arange(5) * 2.5), dtype=object), is_float_index=False | ||||
|         ) | ||||
|         self.check_coerce( | ||||
|             mixed_index, Index([1.5, 2, 3, 4, 5], dtype=object), is_float_index=False | ||||
|         ) | ||||
|  | ||||
|     def test_type_coercion_fail(self, any_int_numpy_dtype): | ||||
|         # see gh-15832 | ||||
|         msg = "Trying to coerce float values to integers" | ||||
|         with pytest.raises(ValueError, match=msg): | ||||
|             Index([1, 2, 3.5], dtype=any_int_numpy_dtype) | ||||
|  | ||||
|     def test_equals_numeric(self): | ||||
|         index_cls = Index | ||||
|  | ||||
|         idx = index_cls([1.0, 2.0]) | ||||
|         assert idx.equals(idx) | ||||
|         assert idx.identical(idx) | ||||
|  | ||||
|         idx2 = index_cls([1.0, 2.0]) | ||||
|         assert idx.equals(idx2) | ||||
|  | ||||
|         idx = index_cls([1.0, np.nan]) | ||||
|         assert idx.equals(idx) | ||||
|         assert idx.identical(idx) | ||||
|  | ||||
|         idx2 = index_cls([1.0, np.nan]) | ||||
|         assert idx.equals(idx2) | ||||
|  | ||||
|     @pytest.mark.parametrize( | ||||
|         "other", | ||||
|         ( | ||||
|             Index([1, 2], dtype=np.int64), | ||||
|             Index([1.0, 2.0], dtype=object), | ||||
|             Index([1, 2], dtype=object), | ||||
|         ), | ||||
|     ) | ||||
|     def test_equals_numeric_other_index_type(self, other): | ||||
|         idx = Index([1.0, 2.0]) | ||||
|         assert idx.equals(other) | ||||
|         assert other.equals(idx) | ||||
|  | ||||
|     @pytest.mark.parametrize( | ||||
|         "vals", | ||||
|         [ | ||||
|             pd.date_range("2016-01-01", periods=3), | ||||
|             pd.timedelta_range("1 Day", periods=3), | ||||
|         ], | ||||
|     ) | ||||
|     def test_lookups_datetimelike_values(self, vals, dtype): | ||||
|         # If we have datetime64 or timedelta64 values, make sure they are | ||||
|         #  wrapped correctly  GH#31163 | ||||
|         ser = Series(vals, index=range(3, 6)) | ||||
|         ser.index = ser.index.astype(dtype) | ||||
|  | ||||
|         expected = vals[1] | ||||
|  | ||||
|         result = ser[4.0] | ||||
|         assert isinstance(result, type(expected)) and result == expected | ||||
|         result = ser[4] | ||||
|         assert isinstance(result, type(expected)) and result == expected | ||||
|  | ||||
|         result = ser.loc[4.0] | ||||
|         assert isinstance(result, type(expected)) and result == expected | ||||
|         result = ser.loc[4] | ||||
|         assert isinstance(result, type(expected)) and result == expected | ||||
|  | ||||
|         result = ser.at[4.0] | ||||
|         assert isinstance(result, type(expected)) and result == expected | ||||
|         # GH#31329 .at[4] should cast to 4.0, matching .loc behavior | ||||
|         result = ser.at[4] | ||||
|         assert isinstance(result, type(expected)) and result == expected | ||||
|  | ||||
|         result = ser.iloc[1] | ||||
|         assert isinstance(result, type(expected)) and result == expected | ||||
|  | ||||
|         result = ser.iat[1] | ||||
|         assert isinstance(result, type(expected)) and result == expected | ||||
|  | ||||
|     def test_doesnt_contain_all_the_things(self): | ||||
|         idx = Index([np.nan]) | ||||
|         assert not idx.isin([0]).item() | ||||
|         assert not idx.isin([1]).item() | ||||
|         assert idx.isin([np.nan]).item() | ||||
|  | ||||
|     def test_nan_multiple_containment(self): | ||||
|         index_cls = Index | ||||
|  | ||||
|         idx = index_cls([1.0, np.nan]) | ||||
|         tm.assert_numpy_array_equal(idx.isin([1.0]), np.array([True, False])) | ||||
|         tm.assert_numpy_array_equal(idx.isin([2.0, np.pi]), np.array([False, False])) | ||||
|         tm.assert_numpy_array_equal(idx.isin([np.nan]), np.array([False, True])) | ||||
|         tm.assert_numpy_array_equal(idx.isin([1.0, np.nan]), np.array([True, True])) | ||||
|         idx = index_cls([1.0, 2.0]) | ||||
|         tm.assert_numpy_array_equal(idx.isin([np.nan]), np.array([False, False])) | ||||
|  | ||||
|     def test_fillna_float64(self): | ||||
|         index_cls = Index | ||||
|         # GH 11343 | ||||
|         idx = Index([1.0, np.nan, 3.0], dtype=float, name="x") | ||||
|         # can't downcast | ||||
|         exp = Index([1.0, 0.1, 3.0], name="x") | ||||
|         tm.assert_index_equal(idx.fillna(0.1), exp, exact=True) | ||||
|  | ||||
|         # downcast | ||||
|         exp = index_cls([1.0, 2.0, 3.0], name="x") | ||||
|         tm.assert_index_equal(idx.fillna(2), exp) | ||||
|  | ||||
|         # object | ||||
|         exp = Index([1.0, "obj", 3.0], name="x") | ||||
|         tm.assert_index_equal(idx.fillna("obj"), exp, exact=True) | ||||
|  | ||||
|     def test_logical_compat(self, simple_index): | ||||
|         idx = simple_index | ||||
|         assert idx.all() == idx.values.all() | ||||
|         assert idx.any() == idx.values.any() | ||||
|  | ||||
|         assert idx.all() == idx.to_series().all() | ||||
|         assert idx.any() == idx.to_series().any() | ||||
|  | ||||
|  | ||||
| class TestNumericInt: | ||||
|     @pytest.fixture(params=[np.int64, np.int32, np.int16, np.int8, np.uint64]) | ||||
|     def dtype(self, request): | ||||
|         return request.param | ||||
|  | ||||
|     @pytest.fixture | ||||
|     def simple_index(self, dtype): | ||||
|         return Index(range(0, 20, 2), dtype=dtype) | ||||
|  | ||||
|     def test_is_monotonic(self): | ||||
|         index_cls = Index | ||||
|  | ||||
|         index = index_cls([1, 2, 3, 4]) | ||||
|         assert index.is_monotonic_increasing is True | ||||
|         assert index.is_monotonic_increasing is True | ||||
|         assert index._is_strictly_monotonic_increasing is True | ||||
|         assert index.is_monotonic_decreasing is False | ||||
|         assert index._is_strictly_monotonic_decreasing is False | ||||
|  | ||||
|         index = index_cls([4, 3, 2, 1]) | ||||
|         assert index.is_monotonic_increasing is False | ||||
|         assert index._is_strictly_monotonic_increasing is False | ||||
|         assert index._is_strictly_monotonic_decreasing is True | ||||
|  | ||||
|         index = index_cls([1]) | ||||
|         assert index.is_monotonic_increasing is True | ||||
|         assert index.is_monotonic_increasing is True | ||||
|         assert index.is_monotonic_decreasing is True | ||||
|         assert index._is_strictly_monotonic_increasing is True | ||||
|         assert index._is_strictly_monotonic_decreasing is True | ||||
|  | ||||
|     def test_is_strictly_monotonic(self): | ||||
|         index_cls = Index | ||||
|  | ||||
|         index = index_cls([1, 1, 2, 3]) | ||||
|         assert index.is_monotonic_increasing is True | ||||
|         assert index._is_strictly_monotonic_increasing is False | ||||
|  | ||||
|         index = index_cls([3, 2, 1, 1]) | ||||
|         assert index.is_monotonic_decreasing is True | ||||
|         assert index._is_strictly_monotonic_decreasing is False | ||||
|  | ||||
|         index = index_cls([1, 1]) | ||||
|         assert index.is_monotonic_increasing | ||||
|         assert index.is_monotonic_decreasing | ||||
|         assert not index._is_strictly_monotonic_increasing | ||||
|         assert not index._is_strictly_monotonic_decreasing | ||||
|  | ||||
|     def test_logical_compat(self, simple_index): | ||||
|         idx = simple_index | ||||
|         assert idx.all() == idx.values.all() | ||||
|         assert idx.any() == idx.values.any() | ||||
|  | ||||
|     def test_identical(self, simple_index, dtype): | ||||
|         index = simple_index | ||||
|  | ||||
|         idx = Index(index.copy()) | ||||
|         assert idx.identical(index) | ||||
|  | ||||
|         same_values_different_type = Index(idx, dtype=object) | ||||
|         assert not idx.identical(same_values_different_type) | ||||
|  | ||||
|         idx = index.astype(dtype=object) | ||||
|         idx = idx.rename("foo") | ||||
|         same_values = Index(idx, dtype=object) | ||||
|         assert same_values.identical(idx) | ||||
|  | ||||
|         assert not idx.identical(index) | ||||
|         assert Index(same_values, name="foo", dtype=object).identical(idx) | ||||
|  | ||||
|         assert not index.astype(dtype=object).identical(index.astype(dtype=dtype)) | ||||
|  | ||||
|     def test_cant_or_shouldnt_cast(self, dtype): | ||||
|         msg = r"invalid literal for int\(\) with base 10: 'foo'" | ||||
|  | ||||
|         # can't | ||||
|         data = ["foo", "bar", "baz"] | ||||
|         with pytest.raises(ValueError, match=msg): | ||||
|             Index(data, dtype=dtype) | ||||
|  | ||||
|     def test_view_index(self, simple_index): | ||||
|         index = simple_index | ||||
|         msg = "Passing a type in .*Index.view is deprecated" | ||||
|         with tm.assert_produces_warning(FutureWarning, match=msg): | ||||
|             index.view(Index) | ||||
|  | ||||
|     def test_prevent_casting(self, simple_index): | ||||
|         index = simple_index | ||||
|         result = index.astype("O") | ||||
|         assert result.dtype == np.object_ | ||||
|  | ||||
|  | ||||
| class TestIntNumericIndex: | ||||
|     @pytest.fixture(params=[np.int64, np.int32, np.int16, np.int8]) | ||||
|     def dtype(self, request): | ||||
|         return request.param | ||||
|  | ||||
|     def test_constructor_from_list_no_dtype(self): | ||||
|         index = Index([1, 2, 3]) | ||||
|         assert index.dtype == np.int64 | ||||
|  | ||||
|     def test_constructor(self, dtype): | ||||
|         index_cls = Index | ||||
|  | ||||
|         # scalar raise Exception | ||||
|         msg = ( | ||||
|             rf"{index_cls.__name__}\(\.\.\.\) must be called with a collection of some " | ||||
|             "kind, 5 was passed" | ||||
|         ) | ||||
|         with pytest.raises(TypeError, match=msg): | ||||
|             index_cls(5) | ||||
|  | ||||
|         # copy | ||||
|         # pass list, coerce fine | ||||
|         index = index_cls([-5, 0, 1, 2], dtype=dtype) | ||||
|         arr = index.values.copy() | ||||
|         new_index = index_cls(arr, copy=True) | ||||
|         tm.assert_index_equal(new_index, index, exact=True) | ||||
|         val = int(arr[0]) + 3000 | ||||
|  | ||||
|         # this should not change index | ||||
|         if dtype != np.int8: | ||||
|             # NEP 50 won't allow assignment that would overflow | ||||
|             arr[0] = val | ||||
|             assert new_index[0] != val | ||||
|  | ||||
|         if dtype == np.int64: | ||||
|             # pass list, coerce fine | ||||
|             index = index_cls([-5, 0, 1, 2], dtype=dtype) | ||||
|             expected = Index([-5, 0, 1, 2], dtype=dtype) | ||||
|             tm.assert_index_equal(index, expected) | ||||
|  | ||||
|             # from iterable | ||||
|             index = index_cls(iter([-5, 0, 1, 2]), dtype=dtype) | ||||
|             expected = index_cls([-5, 0, 1, 2], dtype=dtype) | ||||
|             tm.assert_index_equal(index, expected, exact=True) | ||||
|  | ||||
|             # interpret list-like | ||||
|             expected = index_cls([5, 0], dtype=dtype) | ||||
|             for cls in [Index, index_cls]: | ||||
|                 for idx in [ | ||||
|                     cls([5, 0], dtype=dtype), | ||||
|                     cls(np.array([5, 0]), dtype=dtype), | ||||
|                     cls(Series([5, 0]), dtype=dtype), | ||||
|                 ]: | ||||
|                     tm.assert_index_equal(idx, expected) | ||||
|  | ||||
|     def test_constructor_corner(self, dtype): | ||||
|         index_cls = Index | ||||
|  | ||||
|         arr = np.array([1, 2, 3, 4], dtype=object) | ||||
|  | ||||
|         index = index_cls(arr, dtype=dtype) | ||||
|         assert index.values.dtype == index.dtype | ||||
|         if dtype == np.int64: | ||||
|             without_dtype = Index(arr) | ||||
|             # as of 2.0 we do not infer a dtype when we get an object-dtype | ||||
|             #  ndarray of numbers, matching Series behavior | ||||
|             assert without_dtype.dtype == object | ||||
|  | ||||
|             tm.assert_index_equal(index, without_dtype.astype(np.int64)) | ||||
|  | ||||
|         # preventing casting | ||||
|         arr = np.array([1, "2", 3, "4"], dtype=object) | ||||
|         msg = "Trying to coerce float values to integers" | ||||
|         with pytest.raises(ValueError, match=msg): | ||||
|             index_cls(arr, dtype=dtype) | ||||
|  | ||||
|     def test_constructor_coercion_signed_to_unsigned( | ||||
|         self, | ||||
|         any_unsigned_int_numpy_dtype, | ||||
|     ): | ||||
|         # see gh-15832 | ||||
|         msg = "|".join( | ||||
|             [ | ||||
|                 "Trying to coerce negative values to unsigned integers", | ||||
|                 "The elements provided in the data cannot all be casted", | ||||
|             ] | ||||
|         ) | ||||
|         with pytest.raises(OverflowError, match=msg): | ||||
|             Index([-1], dtype=any_unsigned_int_numpy_dtype) | ||||
|  | ||||
|     def test_constructor_np_signed(self, any_signed_int_numpy_dtype): | ||||
|         # GH#47475 | ||||
|         scalar = np.dtype(any_signed_int_numpy_dtype).type(1) | ||||
|         result = Index([scalar]) | ||||
|         expected = Index([1], dtype=any_signed_int_numpy_dtype) | ||||
|         tm.assert_index_equal(result, expected, exact=True) | ||||
|  | ||||
|     def test_constructor_np_unsigned(self, any_unsigned_int_numpy_dtype): | ||||
|         # GH#47475 | ||||
|         scalar = np.dtype(any_unsigned_int_numpy_dtype).type(1) | ||||
|         result = Index([scalar]) | ||||
|         expected = Index([1], dtype=any_unsigned_int_numpy_dtype) | ||||
|         tm.assert_index_equal(result, expected, exact=True) | ||||
|  | ||||
|     def test_coerce_list(self): | ||||
|         # coerce things | ||||
|         arr = Index([1, 2, 3, 4]) | ||||
|         assert isinstance(arr, Index) | ||||
|  | ||||
|         # but not if explicit dtype passed | ||||
|         arr = Index([1, 2, 3, 4], dtype=object) | ||||
|         assert type(arr) is Index | ||||
|  | ||||
|  | ||||
| class TestFloat16Index: | ||||
|     # float 16 indexes not supported | ||||
|     # GH 49535 | ||||
|     def test_constructor(self): | ||||
|         index_cls = Index | ||||
|         dtype = np.float16 | ||||
|  | ||||
|         msg = "float16 indexes are not supported" | ||||
|  | ||||
|         # explicit construction | ||||
|         with pytest.raises(NotImplementedError, match=msg): | ||||
|             index_cls([1, 2, 3, 4, 5], dtype=dtype) | ||||
|  | ||||
|         with pytest.raises(NotImplementedError, match=msg): | ||||
|             index_cls(np.array([1, 2, 3, 4, 5]), dtype=dtype) | ||||
|  | ||||
|         with pytest.raises(NotImplementedError, match=msg): | ||||
|             index_cls([1.0, 2, 3, 4, 5], dtype=dtype) | ||||
|  | ||||
|         with pytest.raises(NotImplementedError, match=msg): | ||||
|             index_cls(np.array([1.0, 2, 3, 4, 5]), dtype=dtype) | ||||
|  | ||||
|         with pytest.raises(NotImplementedError, match=msg): | ||||
|             index_cls([1.0, 2, 3, 4, 5], dtype=dtype) | ||||
|  | ||||
|         with pytest.raises(NotImplementedError, match=msg): | ||||
|             index_cls(np.array([1.0, 2, 3, 4, 5]), dtype=dtype) | ||||
|  | ||||
|         # nan handling | ||||
|         with pytest.raises(NotImplementedError, match=msg): | ||||
|             index_cls([np.nan, np.nan], dtype=dtype) | ||||
|  | ||||
|         with pytest.raises(NotImplementedError, match=msg): | ||||
|             index_cls(np.array([np.nan]), dtype=dtype) | ||||
|  | ||||
|  | ||||
| @pytest.mark.parametrize( | ||||
|     "box", | ||||
|     [list, lambda x: np.array(x, dtype=object), lambda x: Index(x, dtype=object)], | ||||
| ) | ||||
| def test_uint_index_does_not_convert_to_float64(box): | ||||
|     # https://github.com/pandas-dev/pandas/issues/28279 | ||||
|     # https://github.com/pandas-dev/pandas/issues/28023 | ||||
|     series = Series( | ||||
|         [0, 1, 2, 3, 4, 5], | ||||
|         index=[ | ||||
|             7606741985629028552, | ||||
|             17876870360202815256, | ||||
|             17876870360202815256, | ||||
|             13106359306506049338, | ||||
|             8991270399732411471, | ||||
|             8991270399732411472, | ||||
|         ], | ||||
|     ) | ||||
|  | ||||
|     result = series.loc[box([7606741985629028552, 17876870360202815256])] | ||||
|  | ||||
|     expected = Index( | ||||
|         [7606741985629028552, 17876870360202815256, 17876870360202815256], | ||||
|         dtype="uint64", | ||||
|     ) | ||||
|     tm.assert_index_equal(result.index, expected) | ||||
|  | ||||
|     tm.assert_equal(result, series.iloc[:3]) | ||||
|  | ||||
|  | ||||
| def test_float64_index_equals(): | ||||
|     # https://github.com/pandas-dev/pandas/issues/35217 | ||||
|     float_index = Index([1.0, 2, 3]) | ||||
|     string_index = Index(["1", "2", "3"]) | ||||
|  | ||||
|     result = float_index.equals(string_index) | ||||
|     assert result is False | ||||
|  | ||||
|     result = string_index.equals(float_index) | ||||
|     assert result is False | ||||
|  | ||||
|  | ||||
| def test_map_dtype_inference_unsigned_to_signed(): | ||||
|     # GH#44609 cases where we don't retain dtype | ||||
|     idx = Index([1, 2, 3], dtype=np.uint64) | ||||
|     result = idx.map(lambda x: -x) | ||||
|     expected = Index([-1, -2, -3], dtype=np.int64) | ||||
|     tm.assert_index_equal(result, expected) | ||||
|  | ||||
|  | ||||
| def test_map_dtype_inference_overflows(): | ||||
|     # GH#44609 case where we have to upcast | ||||
|     idx = Index(np.array([1, 2, 3], dtype=np.int8)) | ||||
|     result = idx.map(lambda x: x * 1000) | ||||
|     # TODO: we could plausibly try to infer down to int16 here | ||||
|     expected = Index([1000, 2000, 3000], dtype=np.int64) | ||||
|     tm.assert_index_equal(result, expected) | ||||
|  | ||||
|  | ||||
| def test_view_to_datetimelike(): | ||||
|     # GH#55710 | ||||
|     idx = Index([1, 2, 3]) | ||||
|     res = idx.view("m8[s]") | ||||
|     expected = pd.TimedeltaIndex(idx.values.view("m8[s]")) | ||||
|     tm.assert_index_equal(res, expected) | ||||
|  | ||||
|     res2 = idx.view("m8[D]") | ||||
|     expected2 = idx.values.view("m8[D]") | ||||
|     tm.assert_numpy_array_equal(res2, expected2) | ||||
|  | ||||
|     res3 = idx.view("M8[h]") | ||||
|     expected3 = idx.values.view("M8[h]") | ||||
|     tm.assert_numpy_array_equal(res3, expected3) | ||||
| @ -0,0 +1,168 @@ | ||||
| from datetime import ( | ||||
|     datetime, | ||||
|     timedelta, | ||||
| ) | ||||
|  | ||||
| import numpy as np | ||||
| import pytest | ||||
|  | ||||
| import pandas._testing as tm | ||||
| from pandas.core.indexes.api import ( | ||||
|     Index, | ||||
|     RangeIndex, | ||||
| ) | ||||
|  | ||||
|  | ||||
| @pytest.fixture | ||||
| def index_large(): | ||||
|     # large values used in TestUInt64Index where no compat needed with int64/float64 | ||||
|     large = [2**63, 2**63 + 10, 2**63 + 15, 2**63 + 20, 2**63 + 25] | ||||
|     return Index(large, dtype=np.uint64) | ||||
|  | ||||
|  | ||||
| class TestSetOps: | ||||
|     @pytest.mark.parametrize("dtype", ["f8", "u8", "i8"]) | ||||
|     def test_union_non_numeric(self, dtype): | ||||
|         # corner case, non-numeric | ||||
|         index = Index(np.arange(5, dtype=dtype), dtype=dtype) | ||||
|         assert index.dtype == dtype | ||||
|  | ||||
|         other = Index([datetime.now() + timedelta(i) for i in range(4)], dtype=object) | ||||
|         result = index.union(other) | ||||
|         expected = Index(np.concatenate((index, other))) | ||||
|         tm.assert_index_equal(result, expected) | ||||
|  | ||||
|         result = other.union(index) | ||||
|         expected = Index(np.concatenate((other, index))) | ||||
|         tm.assert_index_equal(result, expected) | ||||
|  | ||||
|     def test_intersection(self): | ||||
|         index = Index(range(5), dtype=np.int64) | ||||
|  | ||||
|         other = Index([1, 2, 3, 4, 5]) | ||||
|         result = index.intersection(other) | ||||
|         expected = Index(np.sort(np.intersect1d(index.values, other.values))) | ||||
|         tm.assert_index_equal(result, expected) | ||||
|  | ||||
|         result = other.intersection(index) | ||||
|         expected = Index( | ||||
|             np.sort(np.asarray(np.intersect1d(index.values, other.values))) | ||||
|         ) | ||||
|         tm.assert_index_equal(result, expected) | ||||
|  | ||||
|     @pytest.mark.parametrize("dtype", ["int64", "uint64"]) | ||||
|     def test_int_float_union_dtype(self, dtype): | ||||
|         # https://github.com/pandas-dev/pandas/issues/26778 | ||||
|         # [u]int | float -> float | ||||
|         index = Index([0, 2, 3], dtype=dtype) | ||||
|         other = Index([0.5, 1.5], dtype=np.float64) | ||||
|         expected = Index([0.0, 0.5, 1.5, 2.0, 3.0], dtype=np.float64) | ||||
|         result = index.union(other) | ||||
|         tm.assert_index_equal(result, expected) | ||||
|  | ||||
|         result = other.union(index) | ||||
|         tm.assert_index_equal(result, expected) | ||||
|  | ||||
|     def test_range_float_union_dtype(self): | ||||
|         # https://github.com/pandas-dev/pandas/issues/26778 | ||||
|         index = RangeIndex(start=0, stop=3) | ||||
|         other = Index([0.5, 1.5], dtype=np.float64) | ||||
|         result = index.union(other) | ||||
|         expected = Index([0.0, 0.5, 1, 1.5, 2.0], dtype=np.float64) | ||||
|         tm.assert_index_equal(result, expected) | ||||
|  | ||||
|         result = other.union(index) | ||||
|         tm.assert_index_equal(result, expected) | ||||
|  | ||||
|     def test_range_uint64_union_dtype(self): | ||||
|         # https://github.com/pandas-dev/pandas/issues/26778 | ||||
|         index = RangeIndex(start=0, stop=3) | ||||
|         other = Index([0, 10], dtype=np.uint64) | ||||
|         result = index.union(other) | ||||
|         expected = Index([0, 1, 2, 10], dtype=object) | ||||
|         tm.assert_index_equal(result, expected) | ||||
|  | ||||
|         result = other.union(index) | ||||
|         tm.assert_index_equal(result, expected) | ||||
|  | ||||
|     def test_float64_index_difference(self): | ||||
|         # https://github.com/pandas-dev/pandas/issues/35217 | ||||
|         float_index = Index([1.0, 2, 3]) | ||||
|         string_index = Index(["1", "2", "3"]) | ||||
|  | ||||
|         result = float_index.difference(string_index) | ||||
|         tm.assert_index_equal(result, float_index) | ||||
|  | ||||
|         result = string_index.difference(float_index) | ||||
|         tm.assert_index_equal(result, string_index) | ||||
|  | ||||
|     def test_intersection_uint64_outside_int64_range(self, index_large): | ||||
|         other = Index([2**63, 2**63 + 5, 2**63 + 10, 2**63 + 15, 2**63 + 20]) | ||||
|         result = index_large.intersection(other) | ||||
|         expected = Index(np.sort(np.intersect1d(index_large.values, other.values))) | ||||
|         tm.assert_index_equal(result, expected) | ||||
|  | ||||
|         result = other.intersection(index_large) | ||||
|         expected = Index( | ||||
|             np.sort(np.asarray(np.intersect1d(index_large.values, other.values))) | ||||
|         ) | ||||
|         tm.assert_index_equal(result, expected) | ||||
|  | ||||
|     @pytest.mark.parametrize( | ||||
|         "index2,keeps_name", | ||||
|         [ | ||||
|             (Index([4, 7, 6, 5, 3], name="index"), True), | ||||
|             (Index([4, 7, 6, 5, 3], name="other"), False), | ||||
|         ], | ||||
|     ) | ||||
|     def test_intersection_monotonic(self, index2, keeps_name, sort): | ||||
|         index1 = Index([5, 3, 2, 4, 1], name="index") | ||||
|         expected = Index([5, 3, 4]) | ||||
|  | ||||
|         if keeps_name: | ||||
|             expected.name = "index" | ||||
|  | ||||
|         result = index1.intersection(index2, sort=sort) | ||||
|         if sort is None: | ||||
|             expected = expected.sort_values() | ||||
|         tm.assert_index_equal(result, expected) | ||||
|  | ||||
|     def test_symmetric_difference(self, sort): | ||||
|         # smoke | ||||
|         index1 = Index([5, 2, 3, 4], name="index1") | ||||
|         index2 = Index([2, 3, 4, 1]) | ||||
|         result = index1.symmetric_difference(index2, sort=sort) | ||||
|         expected = Index([5, 1]) | ||||
|         if sort is not None: | ||||
|             tm.assert_index_equal(result, expected) | ||||
|         else: | ||||
|             tm.assert_index_equal(result, expected.sort_values()) | ||||
|         assert result.name is None | ||||
|         if sort is None: | ||||
|             expected = expected.sort_values() | ||||
|         tm.assert_index_equal(result, expected) | ||||
|  | ||||
|  | ||||
| class TestSetOpsSort: | ||||
|     @pytest.mark.parametrize("slice_", [slice(None), slice(0)]) | ||||
|     def test_union_sort_other_special(self, slice_): | ||||
|         # https://github.com/pandas-dev/pandas/issues/24959 | ||||
|  | ||||
|         idx = Index([1, 0, 2]) | ||||
|         # default, sort=None | ||||
|         other = idx[slice_] | ||||
|         tm.assert_index_equal(idx.union(other), idx) | ||||
|         tm.assert_index_equal(other.union(idx), idx) | ||||
|  | ||||
|         # sort=False | ||||
|         tm.assert_index_equal(idx.union(other, sort=False), idx) | ||||
|  | ||||
|     @pytest.mark.parametrize("slice_", [slice(None), slice(0)]) | ||||
|     def test_union_sort_special_true(self, slice_): | ||||
|         idx = Index([1, 0, 2]) | ||||
|         # default, sort=None | ||||
|         other = idx[slice_] | ||||
|  | ||||
|         result = idx.union(other, sort=True) | ||||
|         expected = Index([0, 1, 2]) | ||||
|         tm.assert_index_equal(result, expected) | ||||
		Reference in New Issue
	
	Block a user