done
This commit is contained in:
		| @ -0,0 +1,164 @@ | ||||
| from datetime import datetime | ||||
|  | ||||
| import numpy as np | ||||
| import pytest | ||||
|  | ||||
| from pandas import ( | ||||
|     Index, | ||||
|     RangeIndex, | ||||
|     Series, | ||||
| ) | ||||
| import pandas._testing as tm | ||||
|  | ||||
|  | ||||
| class TestRangeIndexConstructors: | ||||
|     @pytest.mark.parametrize("name", [None, "foo"]) | ||||
|     @pytest.mark.parametrize( | ||||
|         "args, kwargs, start, stop, step", | ||||
|         [ | ||||
|             ((5,), {}, 0, 5, 1), | ||||
|             ((1, 5), {}, 1, 5, 1), | ||||
|             ((1, 5, 2), {}, 1, 5, 2), | ||||
|             ((0,), {}, 0, 0, 1), | ||||
|             ((0, 0), {}, 0, 0, 1), | ||||
|             ((), {"start": 0}, 0, 0, 1), | ||||
|             ((), {"stop": 0}, 0, 0, 1), | ||||
|         ], | ||||
|     ) | ||||
|     def test_constructor(self, args, kwargs, start, stop, step, name): | ||||
|         result = RangeIndex(*args, name=name, **kwargs) | ||||
|         expected = Index(np.arange(start, stop, step, dtype=np.int64), name=name) | ||||
|         assert isinstance(result, RangeIndex) | ||||
|         assert result.name is name | ||||
|         assert result._range == range(start, stop, step) | ||||
|         tm.assert_index_equal(result, expected, exact="equiv") | ||||
|  | ||||
|     def test_constructor_invalid_args(self): | ||||
|         msg = "RangeIndex\\(\\.\\.\\.\\) must be called with integers" | ||||
|         with pytest.raises(TypeError, match=msg): | ||||
|             RangeIndex() | ||||
|  | ||||
|         with pytest.raises(TypeError, match=msg): | ||||
|             RangeIndex(name="Foo") | ||||
|  | ||||
|         # we don't allow on a bare Index | ||||
|         msg = ( | ||||
|             r"Index\(\.\.\.\) must be called with a collection of some " | ||||
|             r"kind, 0 was passed" | ||||
|         ) | ||||
|         with pytest.raises(TypeError, match=msg): | ||||
|             Index(0) | ||||
|  | ||||
|     @pytest.mark.parametrize( | ||||
|         "args", | ||||
|         [ | ||||
|             Index(["a", "b"]), | ||||
|             Series(["a", "b"]), | ||||
|             np.array(["a", "b"]), | ||||
|             [], | ||||
|             np.arange(0, 10), | ||||
|             np.array([1]), | ||||
|             [1], | ||||
|         ], | ||||
|     ) | ||||
|     def test_constructor_additional_invalid_args(self, args): | ||||
|         msg = f"Value needs to be a scalar value, was type {type(args).__name__}" | ||||
|         with pytest.raises(TypeError, match=msg): | ||||
|             RangeIndex(args) | ||||
|  | ||||
|     @pytest.mark.parametrize("args", ["foo", datetime(2000, 1, 1, 0, 0)]) | ||||
|     def test_constructor_invalid_args_wrong_type(self, args): | ||||
|         msg = f"Wrong type {type(args)} for value {args}" | ||||
|         with pytest.raises(TypeError, match=msg): | ||||
|             RangeIndex(args) | ||||
|  | ||||
|     def test_constructor_same(self): | ||||
|         # pass thru w and w/o copy | ||||
|         index = RangeIndex(1, 5, 2) | ||||
|         result = RangeIndex(index, copy=False) | ||||
|         assert result.identical(index) | ||||
|  | ||||
|         result = RangeIndex(index, copy=True) | ||||
|         tm.assert_index_equal(result, index, exact=True) | ||||
|  | ||||
|         result = RangeIndex(index) | ||||
|         tm.assert_index_equal(result, index, exact=True) | ||||
|  | ||||
|         with pytest.raises( | ||||
|             ValueError, | ||||
|             match="Incorrect `dtype` passed: expected signed integer, received float64", | ||||
|         ): | ||||
|             RangeIndex(index, dtype="float64") | ||||
|  | ||||
|     def test_constructor_range_object(self): | ||||
|         result = RangeIndex(range(1, 5, 2)) | ||||
|         expected = RangeIndex(1, 5, 2) | ||||
|         tm.assert_index_equal(result, expected, exact=True) | ||||
|  | ||||
|     def test_constructor_range(self): | ||||
|         result = RangeIndex.from_range(range(1, 5, 2)) | ||||
|         expected = RangeIndex(1, 5, 2) | ||||
|         tm.assert_index_equal(result, expected, exact=True) | ||||
|  | ||||
|         result = RangeIndex.from_range(range(5, 6)) | ||||
|         expected = RangeIndex(5, 6, 1) | ||||
|         tm.assert_index_equal(result, expected, exact=True) | ||||
|  | ||||
|         # an invalid range | ||||
|         result = RangeIndex.from_range(range(5, 1)) | ||||
|         expected = RangeIndex(0, 0, 1) | ||||
|         tm.assert_index_equal(result, expected, exact=True) | ||||
|  | ||||
|         result = RangeIndex.from_range(range(5)) | ||||
|         expected = RangeIndex(0, 5, 1) | ||||
|         tm.assert_index_equal(result, expected, exact=True) | ||||
|  | ||||
|         result = Index(range(1, 5, 2)) | ||||
|         expected = RangeIndex(1, 5, 2) | ||||
|         tm.assert_index_equal(result, expected, exact=True) | ||||
|  | ||||
|         msg = ( | ||||
|             r"(RangeIndex.)?from_range\(\) got an unexpected keyword argument( 'copy')?" | ||||
|         ) | ||||
|         with pytest.raises(TypeError, match=msg): | ||||
|             RangeIndex.from_range(range(10), copy=True) | ||||
|  | ||||
|     def test_constructor_name(self): | ||||
|         # GH#12288 | ||||
|         orig = RangeIndex(10) | ||||
|         orig.name = "original" | ||||
|  | ||||
|         copy = RangeIndex(orig) | ||||
|         copy.name = "copy" | ||||
|  | ||||
|         assert orig.name == "original" | ||||
|         assert copy.name == "copy" | ||||
|  | ||||
|         new = Index(copy) | ||||
|         assert new.name == "copy" | ||||
|  | ||||
|         new.name = "new" | ||||
|         assert orig.name == "original" | ||||
|         assert copy.name == "copy" | ||||
|         assert new.name == "new" | ||||
|  | ||||
|     def test_constructor_corner(self): | ||||
|         arr = np.array([1, 2, 3, 4], dtype=object) | ||||
|         index = RangeIndex(1, 5) | ||||
|         assert index.values.dtype == np.int64 | ||||
|         expected = Index(arr).astype("int64") | ||||
|  | ||||
|         tm.assert_index_equal(index, expected, exact="equiv") | ||||
|  | ||||
|         # non-int raise Exception | ||||
|         with pytest.raises(TypeError, match=r"Wrong type \<class 'str'\>"): | ||||
|             RangeIndex("1", "10", "1") | ||||
|         with pytest.raises(TypeError, match=r"Wrong type \<class 'float'\>"): | ||||
|             RangeIndex(1.1, 10.2, 1.3) | ||||
|  | ||||
|         # invalid passed type | ||||
|         with pytest.raises( | ||||
|             ValueError, | ||||
|             match="Incorrect `dtype` passed: expected signed integer, received float64", | ||||
|         ): | ||||
|             RangeIndex(1, 5, dtype="float64") | ||||
| @ -0,0 +1,137 @@ | ||||
| import numpy as np | ||||
| import pytest | ||||
|  | ||||
| from pandas import ( | ||||
|     Index, | ||||
|     RangeIndex, | ||||
| ) | ||||
| import pandas._testing as tm | ||||
|  | ||||
|  | ||||
| class TestGetIndexer: | ||||
|     def test_get_indexer(self): | ||||
|         index = RangeIndex(start=0, stop=20, step=2) | ||||
|         target = RangeIndex(10) | ||||
|         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) | ||||
|  | ||||
|     def test_get_indexer_pad(self): | ||||
|         index = RangeIndex(start=0, stop=20, step=2) | ||||
|         target = RangeIndex(10) | ||||
|         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) | ||||
|  | ||||
|     def test_get_indexer_backfill(self): | ||||
|         index = RangeIndex(start=0, stop=20, step=2) | ||||
|         target = RangeIndex(10) | ||||
|         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_limit(self): | ||||
|         # GH#28631 | ||||
|         idx = RangeIndex(4) | ||||
|         target = RangeIndex(6) | ||||
|         result = idx.get_indexer(target, method="pad", limit=1) | ||||
|         expected = np.array([0, 1, 2, 3, 3, -1], dtype=np.intp) | ||||
|         tm.assert_numpy_array_equal(result, expected) | ||||
|  | ||||
|     @pytest.mark.parametrize("stop", [0, -1, -2]) | ||||
|     def test_get_indexer_decreasing(self, stop): | ||||
|         # GH#28678 | ||||
|         index = RangeIndex(7, stop, -3) | ||||
|         result = index.get_indexer(range(9)) | ||||
|         expected = np.array([-1, 2, -1, -1, 1, -1, -1, 0, -1], dtype=np.intp) | ||||
|         tm.assert_numpy_array_equal(result, expected) | ||||
|  | ||||
|  | ||||
| class TestTake: | ||||
|     def test_take_preserve_name(self): | ||||
|         index = RangeIndex(1, 5, name="foo") | ||||
|         taken = index.take([3, 0, 1]) | ||||
|         assert index.name == taken.name | ||||
|  | ||||
|     def test_take_fill_value(self): | ||||
|         # GH#12631 | ||||
|         idx = RangeIndex(1, 4, name="xxx") | ||||
|         result = idx.take(np.array([1, 0, -1])) | ||||
|         expected = Index([2, 1, 3], dtype=np.int64, name="xxx") | ||||
|         tm.assert_index_equal(result, expected) | ||||
|  | ||||
|         # fill_value | ||||
|         msg = "Unable to fill values because RangeIndex cannot contain NA" | ||||
|         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=np.int64, name="xxx") | ||||
|         tm.assert_index_equal(result, expected) | ||||
|  | ||||
|         msg = "Unable to fill values because RangeIndex cannot contain NA" | ||||
|         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) | ||||
|  | ||||
|     def test_take_raises_index_error(self): | ||||
|         idx = RangeIndex(1, 4, name="xxx") | ||||
|  | ||||
|         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])) | ||||
|  | ||||
|         msg = "index -4 is out of bounds for (axis 0 with )?size 3" | ||||
|         with pytest.raises(IndexError, match=msg): | ||||
|             idx.take(np.array([1, -4])) | ||||
|  | ||||
|         # no errors | ||||
|         result = idx.take(np.array([1, -3])) | ||||
|         expected = Index([2, 1], dtype=np.int64, name="xxx") | ||||
|         tm.assert_index_equal(result, expected) | ||||
|  | ||||
|     def test_take_accepts_empty_array(self): | ||||
|         idx = RangeIndex(1, 4, name="foo") | ||||
|         result = idx.take(np.array([])) | ||||
|         expected = Index([], dtype=np.int64, name="foo") | ||||
|         tm.assert_index_equal(result, expected) | ||||
|  | ||||
|         # empty index | ||||
|         idx = RangeIndex(0, name="foo") | ||||
|         result = idx.take(np.array([])) | ||||
|         expected = Index([], dtype=np.int64, name="foo") | ||||
|         tm.assert_index_equal(result, expected) | ||||
|  | ||||
|     def test_take_accepts_non_int64_array(self): | ||||
|         idx = RangeIndex(1, 4, name="foo") | ||||
|         result = idx.take(np.array([2, 1], dtype=np.uint32)) | ||||
|         expected = Index([3, 2], dtype=np.int64, name="foo") | ||||
|         tm.assert_index_equal(result, expected) | ||||
|  | ||||
|     def test_take_when_index_has_step(self): | ||||
|         idx = RangeIndex(1, 11, 3, name="foo")  # [1, 4, 7, 10] | ||||
|         result = idx.take(np.array([1, 0, -1, -4])) | ||||
|         expected = Index([4, 1, 10, 1], dtype=np.int64, name="foo") | ||||
|         tm.assert_index_equal(result, expected) | ||||
|  | ||||
|     def test_take_when_index_has_negative_step(self): | ||||
|         idx = RangeIndex(11, -4, -2, name="foo")  # [11, 9, 7, 5, 3, 1, -1, -3] | ||||
|         result = idx.take(np.array([1, 0, -1, -8])) | ||||
|         expected = Index([9, 11, -3, 11], dtype=np.int64, name="foo") | ||||
|         tm.assert_index_equal(result, expected) | ||||
|  | ||||
|  | ||||
| class TestWhere: | ||||
|     def test_where_putmask_range_cast(self): | ||||
|         # GH#43240 | ||||
|         idx = RangeIndex(0, 5, name="test") | ||||
|  | ||||
|         mask = np.array([True, True, False, False, False]) | ||||
|         result = idx.putmask(mask, 10) | ||||
|         expected = Index([10, 10, 2, 3, 4], dtype=np.int64, name="test") | ||||
|         tm.assert_index_equal(result, expected) | ||||
|  | ||||
|         result = idx.where(~mask, 10) | ||||
|         tm.assert_index_equal(result, expected) | ||||
| @ -0,0 +1,177 @@ | ||||
| import numpy as np | ||||
|  | ||||
| from pandas import ( | ||||
|     Index, | ||||
|     RangeIndex, | ||||
| ) | ||||
| import pandas._testing as tm | ||||
|  | ||||
|  | ||||
| class TestJoin: | ||||
|     def test_join_outer(self): | ||||
|         # join with Index[int64] | ||||
|         index = RangeIndex(start=0, stop=20, step=2) | ||||
|         other = Index(np.arange(25, 14, -1, dtype=np.int64)) | ||||
|  | ||||
|         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, 2, 4, 6, 8, 10, 12, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25] | ||||
|         ) | ||||
|         elidx = np.array( | ||||
|             [0, 1, 2, 3, 4, 5, 6, 7, -1, 8, -1, 9, -1, -1, -1, -1, -1, -1, -1], | ||||
|             dtype=np.intp, | ||||
|         ) | ||||
|         eridx = np.array( | ||||
|             [-1, -1, -1, -1, -1, -1, -1, -1, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0], | ||||
|             dtype=np.intp, | ||||
|         ) | ||||
|  | ||||
|         assert isinstance(res, Index) and res.dtype == np.dtype(np.int64) | ||||
|         assert not isinstance(res, RangeIndex) | ||||
|         tm.assert_index_equal(res, eres, exact=True) | ||||
|         tm.assert_numpy_array_equal(lidx, elidx) | ||||
|         tm.assert_numpy_array_equal(ridx, eridx) | ||||
|  | ||||
|         # join with RangeIndex | ||||
|         other = RangeIndex(25, 14, -1) | ||||
|  | ||||
|         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) | ||||
|  | ||||
|         assert isinstance(res, Index) and res.dtype == np.int64 | ||||
|         assert not isinstance(res, RangeIndex) | ||||
|         tm.assert_index_equal(res, eres) | ||||
|         tm.assert_numpy_array_equal(lidx, elidx) | ||||
|         tm.assert_numpy_array_equal(ridx, eridx) | ||||
|  | ||||
|     def test_join_inner(self): | ||||
|         # Join with non-RangeIndex | ||||
|         index = RangeIndex(start=0, stop=20, step=2) | ||||
|         other = Index(np.arange(25, 14, -1, dtype=np.int64)) | ||||
|  | ||||
|         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([16, 18]) | ||||
|         elidx = np.array([8, 9], dtype=np.intp) | ||||
|         eridx = np.array([9, 7], 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) | ||||
|  | ||||
|         # Join two RangeIndex | ||||
|         other = RangeIndex(25, 14, -1) | ||||
|  | ||||
|         res, lidx, ridx = index.join(other, how="inner", return_indexers=True) | ||||
|  | ||||
|         assert isinstance(res, RangeIndex) | ||||
|         tm.assert_index_equal(res, eres, exact="equiv") | ||||
|         tm.assert_numpy_array_equal(lidx, elidx) | ||||
|         tm.assert_numpy_array_equal(ridx, eridx) | ||||
|  | ||||
|     def test_join_left(self): | ||||
|         # Join with Index[int64] | ||||
|         index = RangeIndex(start=0, stop=20, step=2) | ||||
|         other = Index(np.arange(25, 14, -1, dtype=np.int64)) | ||||
|  | ||||
|         res, lidx, ridx = index.join(other, how="left", return_indexers=True) | ||||
|         eres = index | ||||
|         eridx = np.array([-1, -1, -1, -1, -1, -1, -1, -1, 9, 7], dtype=np.intp) | ||||
|  | ||||
|         assert isinstance(res, RangeIndex) | ||||
|         tm.assert_index_equal(res, eres) | ||||
|         assert lidx is None | ||||
|         tm.assert_numpy_array_equal(ridx, eridx) | ||||
|  | ||||
|         # Join withRangeIndex | ||||
|         other = Index(np.arange(25, 14, -1, dtype=np.int64)) | ||||
|  | ||||
|         res, lidx, ridx = index.join(other, how="left", return_indexers=True) | ||||
|  | ||||
|         assert isinstance(res, RangeIndex) | ||||
|         tm.assert_index_equal(res, eres) | ||||
|         assert lidx is None | ||||
|         tm.assert_numpy_array_equal(ridx, eridx) | ||||
|  | ||||
|     def test_join_right(self): | ||||
|         # Join with Index[int64] | ||||
|         index = RangeIndex(start=0, stop=20, step=2) | ||||
|         other = Index(np.arange(25, 14, -1, dtype=np.int64)) | ||||
|  | ||||
|         res, lidx, ridx = index.join(other, how="right", return_indexers=True) | ||||
|         eres = other | ||||
|         elidx = np.array([-1, -1, -1, -1, -1, -1, -1, 9, -1, 8, -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 | ||||
|  | ||||
|         # Join withRangeIndex | ||||
|         other = RangeIndex(25, 14, -1) | ||||
|  | ||||
|         res, lidx, ridx = index.join(other, how="right", return_indexers=True) | ||||
|         eres = other | ||||
|  | ||||
|         assert isinstance(other, RangeIndex) | ||||
|         tm.assert_index_equal(res, eres) | ||||
|         tm.assert_numpy_array_equal(lidx, elidx) | ||||
|         assert ridx is None | ||||
|  | ||||
|     def test_join_non_int_index(self): | ||||
|         index = RangeIndex(start=0, stop=20, step=2) | ||||
|         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_non_unique(self): | ||||
|         index = RangeIndex(start=0, stop=20, step=2) | ||||
|         other = Index([4, 4, 3, 3]) | ||||
|  | ||||
|         res, lidx, ridx = index.join(other, return_indexers=True) | ||||
|  | ||||
|         eres = Index([0, 2, 4, 4, 6, 8, 10, 12, 14, 16, 18]) | ||||
|         elidx = np.array([0, 1, 2, 2, 3, 4, 5, 6, 7, 8, 9], dtype=np.intp) | ||||
|         eridx = np.array([-1, -1, 0, 1, -1, -1, -1, -1, -1, -1, -1], 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_self(self, join_type): | ||||
|         index = RangeIndex(start=0, stop=20, step=2) | ||||
|         joined = index.join(index, how=join_type) | ||||
|         assert index is joined | ||||
| @ -0,0 +1,622 @@ | ||||
| import numpy as np | ||||
| import pytest | ||||
|  | ||||
| from pandas.core.dtypes.common import ensure_platform_int | ||||
|  | ||||
| import pandas as pd | ||||
| from pandas import ( | ||||
|     Index, | ||||
|     RangeIndex, | ||||
| ) | ||||
| import pandas._testing as tm | ||||
|  | ||||
|  | ||||
| class TestRangeIndex: | ||||
|     @pytest.fixture | ||||
|     def simple_index(self): | ||||
|         return RangeIndex(start=0, stop=20, step=2) | ||||
|  | ||||
|     def test_constructor_unwraps_index(self): | ||||
|         result = RangeIndex(1, 3) | ||||
|         expected = np.array([1, 2], dtype=np.int64) | ||||
|         tm.assert_numpy_array_equal(result._data, expected) | ||||
|  | ||||
|     def test_can_hold_identifiers(self, simple_index): | ||||
|         idx = simple_index | ||||
|         key = idx[0] | ||||
|         assert idx._can_hold_identifiers_and_holds_name(key) is False | ||||
|  | ||||
|     def test_too_many_names(self, simple_index): | ||||
|         index = simple_index | ||||
|         with pytest.raises(ValueError, match="^Length"): | ||||
|             index.names = ["roger", "harold"] | ||||
|  | ||||
|     @pytest.mark.parametrize( | ||||
|         "index, start, stop, step", | ||||
|         [ | ||||
|             (RangeIndex(5), 0, 5, 1), | ||||
|             (RangeIndex(0, 5), 0, 5, 1), | ||||
|             (RangeIndex(5, step=2), 0, 5, 2), | ||||
|             (RangeIndex(1, 5, 2), 1, 5, 2), | ||||
|         ], | ||||
|     ) | ||||
|     def test_start_stop_step_attrs(self, index, start, stop, step): | ||||
|         # GH 25710 | ||||
|         assert index.start == start | ||||
|         assert index.stop == stop | ||||
|         assert index.step == step | ||||
|  | ||||
|     def test_copy(self): | ||||
|         i = RangeIndex(5, name="Foo") | ||||
|         i_copy = i.copy() | ||||
|         assert i_copy is not i | ||||
|         assert i_copy.identical(i) | ||||
|         assert i_copy._range == range(0, 5, 1) | ||||
|         assert i_copy.name == "Foo" | ||||
|  | ||||
|     def test_repr(self): | ||||
|         i = RangeIndex(5, name="Foo") | ||||
|         result = repr(i) | ||||
|         expected = "RangeIndex(start=0, stop=5, step=1, name='Foo')" | ||||
|         assert result == expected | ||||
|  | ||||
|         result = eval(result) | ||||
|         tm.assert_index_equal(result, i, exact=True) | ||||
|  | ||||
|         i = RangeIndex(5, 0, -1) | ||||
|         result = repr(i) | ||||
|         expected = "RangeIndex(start=5, stop=0, step=-1)" | ||||
|         assert result == expected | ||||
|  | ||||
|         result = eval(result) | ||||
|         tm.assert_index_equal(result, i, exact=True) | ||||
|  | ||||
|     def test_insert(self): | ||||
|         idx = RangeIndex(5, name="Foo") | ||||
|         result = idx[1:4] | ||||
|  | ||||
|         # test 0th element | ||||
|         tm.assert_index_equal(idx[0:4], result.insert(0, idx[0]), exact="equiv") | ||||
|  | ||||
|         # GH 18295 (test missing) | ||||
|         expected = Index([0, np.nan, 1, 2, 3, 4], dtype=np.float64) | ||||
|         for na in [np.nan, None, pd.NA]: | ||||
|             result = RangeIndex(5).insert(1, na) | ||||
|             tm.assert_index_equal(result, expected) | ||||
|  | ||||
|         result = RangeIndex(5).insert(1, pd.NaT) | ||||
|         expected = Index([0, pd.NaT, 1, 2, 3, 4], dtype=object) | ||||
|         tm.assert_index_equal(result, expected) | ||||
|  | ||||
|     def test_insert_edges_preserves_rangeindex(self): | ||||
|         idx = Index(range(4, 9, 2)) | ||||
|  | ||||
|         result = idx.insert(0, 2) | ||||
|         expected = Index(range(2, 9, 2)) | ||||
|         tm.assert_index_equal(result, expected, exact=True) | ||||
|  | ||||
|         result = idx.insert(3, 10) | ||||
|         expected = Index(range(4, 11, 2)) | ||||
|         tm.assert_index_equal(result, expected, exact=True) | ||||
|  | ||||
|     def test_insert_middle_preserves_rangeindex(self): | ||||
|         # insert in the middle | ||||
|         idx = Index(range(0, 3, 2)) | ||||
|         result = idx.insert(1, 1) | ||||
|         expected = Index(range(3)) | ||||
|         tm.assert_index_equal(result, expected, exact=True) | ||||
|  | ||||
|         idx = idx * 2 | ||||
|         result = idx.insert(1, 2) | ||||
|         expected = expected * 2 | ||||
|         tm.assert_index_equal(result, expected, exact=True) | ||||
|  | ||||
|     def test_delete(self): | ||||
|         idx = RangeIndex(5, name="Foo") | ||||
|         expected = idx[1:] | ||||
|         result = idx.delete(0) | ||||
|         tm.assert_index_equal(result, expected, exact=True) | ||||
|         assert result.name == expected.name | ||||
|  | ||||
|         expected = idx[:-1] | ||||
|         result = idx.delete(-1) | ||||
|         tm.assert_index_equal(result, expected, exact=True) | ||||
|         assert result.name == expected.name | ||||
|  | ||||
|         msg = "index 5 is out of bounds for axis 0 with size 5" | ||||
|         with pytest.raises((IndexError, ValueError), match=msg): | ||||
|             # either depending on numpy version | ||||
|             result = idx.delete(len(idx)) | ||||
|  | ||||
|     def test_delete_preserves_rangeindex(self): | ||||
|         idx = Index(range(2), name="foo") | ||||
|  | ||||
|         result = idx.delete([1]) | ||||
|         expected = Index(range(1), name="foo") | ||||
|         tm.assert_index_equal(result, expected, exact=True) | ||||
|  | ||||
|         result = idx.delete(1) | ||||
|         tm.assert_index_equal(result, expected, exact=True) | ||||
|  | ||||
|     def test_delete_preserves_rangeindex_middle(self): | ||||
|         idx = Index(range(3), name="foo") | ||||
|         result = idx.delete(1) | ||||
|         expected = idx[::2] | ||||
|         tm.assert_index_equal(result, expected, exact=True) | ||||
|  | ||||
|         result = idx.delete(-2) | ||||
|         tm.assert_index_equal(result, expected, exact=True) | ||||
|  | ||||
|     def test_delete_preserves_rangeindex_list_at_end(self): | ||||
|         idx = RangeIndex(0, 6, 1) | ||||
|  | ||||
|         loc = [2, 3, 4, 5] | ||||
|         result = idx.delete(loc) | ||||
|         expected = idx[:2] | ||||
|         tm.assert_index_equal(result, expected, exact=True) | ||||
|  | ||||
|         result = idx.delete(loc[::-1]) | ||||
|         tm.assert_index_equal(result, expected, exact=True) | ||||
|  | ||||
|     def test_delete_preserves_rangeindex_list_middle(self): | ||||
|         idx = RangeIndex(0, 6, 1) | ||||
|  | ||||
|         loc = [1, 2, 3, 4] | ||||
|         result = idx.delete(loc) | ||||
|         expected = RangeIndex(0, 6, 5) | ||||
|         tm.assert_index_equal(result, expected, exact=True) | ||||
|  | ||||
|         result = idx.delete(loc[::-1]) | ||||
|         tm.assert_index_equal(result, expected, exact=True) | ||||
|  | ||||
|     def test_delete_all_preserves_rangeindex(self): | ||||
|         idx = RangeIndex(0, 6, 1) | ||||
|  | ||||
|         loc = [0, 1, 2, 3, 4, 5] | ||||
|         result = idx.delete(loc) | ||||
|         expected = idx[:0] | ||||
|         tm.assert_index_equal(result, expected, exact=True) | ||||
|  | ||||
|         result = idx.delete(loc[::-1]) | ||||
|         tm.assert_index_equal(result, expected, exact=True) | ||||
|  | ||||
|     def test_delete_not_preserving_rangeindex(self): | ||||
|         idx = RangeIndex(0, 6, 1) | ||||
|  | ||||
|         loc = [0, 3, 5] | ||||
|         result = idx.delete(loc) | ||||
|         expected = Index([1, 2, 4]) | ||||
|         tm.assert_index_equal(result, expected, exact=True) | ||||
|  | ||||
|         result = idx.delete(loc[::-1]) | ||||
|         tm.assert_index_equal(result, expected, exact=True) | ||||
|  | ||||
|     def test_view(self): | ||||
|         i = RangeIndex(0, name="Foo") | ||||
|         i_view = i.view() | ||||
|         assert i_view.name == "Foo" | ||||
|  | ||||
|         i_view = i.view("i8") | ||||
|         tm.assert_numpy_array_equal(i.values, i_view) | ||||
|  | ||||
|         msg = "Passing a type in RangeIndex.view is deprecated" | ||||
|         with tm.assert_produces_warning(FutureWarning, match=msg): | ||||
|             i_view = i.view(RangeIndex) | ||||
|         tm.assert_index_equal(i, i_view) | ||||
|  | ||||
|     def test_dtype(self, simple_index): | ||||
|         index = simple_index | ||||
|         assert index.dtype == np.int64 | ||||
|  | ||||
|     def test_cache(self): | ||||
|         # GH 26565, GH26617, GH35432, GH53387 | ||||
|         # This test checks whether _cache has been set. | ||||
|         # Calling RangeIndex._cache["_data"] creates an int64 array of the same length | ||||
|         # as the RangeIndex and stores it in _cache. | ||||
|         idx = RangeIndex(0, 100, 10) | ||||
|  | ||||
|         assert idx._cache == {} | ||||
|  | ||||
|         repr(idx) | ||||
|         assert idx._cache == {} | ||||
|  | ||||
|         str(idx) | ||||
|         assert idx._cache == {} | ||||
|  | ||||
|         idx.get_loc(20) | ||||
|         assert idx._cache == {} | ||||
|  | ||||
|         90 in idx  # True | ||||
|         assert idx._cache == {} | ||||
|  | ||||
|         91 in idx  # False | ||||
|         assert idx._cache == {} | ||||
|  | ||||
|         idx.all() | ||||
|         assert idx._cache == {} | ||||
|  | ||||
|         idx.any() | ||||
|         assert idx._cache == {} | ||||
|  | ||||
|         for _ in idx: | ||||
|             pass | ||||
|         assert idx._cache == {} | ||||
|  | ||||
|         msg = "RangeIndex.format is deprecated" | ||||
|         with tm.assert_produces_warning(FutureWarning, match=msg): | ||||
|             idx.format() | ||||
|         assert idx._cache == {} | ||||
|  | ||||
|         df = pd.DataFrame({"a": range(10)}, index=idx) | ||||
|  | ||||
|         # df.__repr__ should not populate index cache | ||||
|         str(df) | ||||
|         assert idx._cache == {} | ||||
|  | ||||
|         df.loc[50] | ||||
|         assert idx._cache == {} | ||||
|  | ||||
|         with pytest.raises(KeyError, match="51"): | ||||
|             df.loc[51] | ||||
|         assert idx._cache == {} | ||||
|  | ||||
|         df.loc[10:50] | ||||
|         assert idx._cache == {} | ||||
|  | ||||
|         df.iloc[5:10] | ||||
|         assert idx._cache == {} | ||||
|  | ||||
|         # after calling take, _cache may contain other keys, but not "_data" | ||||
|         idx.take([3, 0, 1]) | ||||
|         assert "_data" not in idx._cache | ||||
|  | ||||
|         df.loc[[50]] | ||||
|         assert "_data" not in idx._cache | ||||
|  | ||||
|         df.iloc[[5, 6, 7, 8, 9]] | ||||
|         assert "_data" not in idx._cache | ||||
|  | ||||
|         # idx._cache should contain a _data entry after call to idx._data | ||||
|         idx._data | ||||
|         assert isinstance(idx._data, np.ndarray) | ||||
|         assert idx._data is idx._data  # check cached value is reused | ||||
|         assert "_data" in idx._cache | ||||
|         expected = np.arange(0, 100, 10, dtype="int64") | ||||
|         tm.assert_numpy_array_equal(idx._cache["_data"], expected) | ||||
|  | ||||
|     def test_is_monotonic(self): | ||||
|         index = RangeIndex(0, 20, 2) | ||||
|         assert index.is_monotonic_increasing is True | ||||
|         assert index.is_monotonic_increasing is True | ||||
|         assert index.is_monotonic_decreasing is False | ||||
|         assert index._is_strictly_monotonic_increasing is True | ||||
|         assert index._is_strictly_monotonic_decreasing is False | ||||
|  | ||||
|         index = RangeIndex(4, 0, -1) | ||||
|         assert index.is_monotonic_increasing is False | ||||
|         assert index._is_strictly_monotonic_increasing is False | ||||
|         assert index.is_monotonic_decreasing is True | ||||
|         assert index._is_strictly_monotonic_decreasing is True | ||||
|  | ||||
|         index = RangeIndex(1, 2) | ||||
|         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 | ||||
|  | ||||
|         index = RangeIndex(2, 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 | ||||
|  | ||||
|         index = RangeIndex(1, 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 | ||||
|  | ||||
|     @pytest.mark.parametrize( | ||||
|         "left,right", | ||||
|         [ | ||||
|             (RangeIndex(0, 9, 2), RangeIndex(0, 10, 2)), | ||||
|             (RangeIndex(0), RangeIndex(1, -1, 3)), | ||||
|             (RangeIndex(1, 2, 3), RangeIndex(1, 3, 4)), | ||||
|             (RangeIndex(0, -9, -2), RangeIndex(0, -10, -2)), | ||||
|         ], | ||||
|     ) | ||||
|     def test_equals_range(self, left, right): | ||||
|         assert left.equals(right) | ||||
|         assert right.equals(left) | ||||
|  | ||||
|     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): | ||||
|         index = simple_index | ||||
|         i = Index(index.copy()) | ||||
|         assert i.identical(index) | ||||
|  | ||||
|         # we don't allow object dtype for RangeIndex | ||||
|         if isinstance(index, RangeIndex): | ||||
|             return | ||||
|  | ||||
|         same_values_different_type = Index(i, dtype=object) | ||||
|         assert not i.identical(same_values_different_type) | ||||
|  | ||||
|         i = index.copy(dtype=object) | ||||
|         i = i.rename("foo") | ||||
|         same_values = Index(i, dtype=object) | ||||
|         assert same_values.identical(index.copy(dtype=object)) | ||||
|  | ||||
|         assert not i.identical(index) | ||||
|         assert Index(same_values, name="foo", dtype=object).identical(i) | ||||
|  | ||||
|         assert not index.copy(dtype=object).identical(index.copy(dtype="int64")) | ||||
|  | ||||
|     def test_nbytes(self): | ||||
|         # memory savings vs int index | ||||
|         idx = RangeIndex(0, 1000) | ||||
|         assert idx.nbytes < Index(idx._values).nbytes / 10 | ||||
|  | ||||
|         # constant memory usage | ||||
|         i2 = RangeIndex(0, 10) | ||||
|         assert idx.nbytes == i2.nbytes | ||||
|  | ||||
|     @pytest.mark.parametrize( | ||||
|         "start,stop,step", | ||||
|         [ | ||||
|             # can't | ||||
|             ("foo", "bar", "baz"), | ||||
|             # shouldn't | ||||
|             ("0", "1", "2"), | ||||
|         ], | ||||
|     ) | ||||
|     def test_cant_or_shouldnt_cast(self, start, stop, step): | ||||
|         msg = f"Wrong type {type(start)} for value {start}" | ||||
|         with pytest.raises(TypeError, match=msg): | ||||
|             RangeIndex(start, stop, step) | ||||
|  | ||||
|     def test_view_index(self, simple_index): | ||||
|         index = simple_index | ||||
|         msg = "Passing a type in RangeIndex.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_ | ||||
|  | ||||
|     def test_repr_roundtrip(self, simple_index): | ||||
|         index = simple_index | ||||
|         tm.assert_index_equal(eval(repr(index)), index) | ||||
|  | ||||
|     def test_slice_keep_name(self): | ||||
|         idx = RangeIndex(1, 2, name="asdf") | ||||
|         assert idx.name == idx[1:].name | ||||
|  | ||||
|     @pytest.mark.parametrize( | ||||
|         "index", | ||||
|         [ | ||||
|             RangeIndex(start=0, stop=20, step=2, name="foo"), | ||||
|             RangeIndex(start=18, stop=-1, step=-2, name="bar"), | ||||
|         ], | ||||
|         ids=["index_inc", "index_dec"], | ||||
|     ) | ||||
|     def test_has_duplicates(self, index): | ||||
|         assert index.is_unique | ||||
|         assert not index.has_duplicates | ||||
|  | ||||
|     def test_extended_gcd(self, simple_index): | ||||
|         index = simple_index | ||||
|         result = index._extended_gcd(6, 10) | ||||
|         assert result[0] == result[1] * 6 + result[2] * 10 | ||||
|         assert 2 == result[0] | ||||
|  | ||||
|         result = index._extended_gcd(10, 6) | ||||
|         assert 2 == result[1] * 10 + result[2] * 6 | ||||
|         assert 2 == result[0] | ||||
|  | ||||
|     def test_min_fitting_element(self): | ||||
|         result = RangeIndex(0, 20, 2)._min_fitting_element(1) | ||||
|         assert 2 == result | ||||
|  | ||||
|         result = RangeIndex(1, 6)._min_fitting_element(1) | ||||
|         assert 1 == result | ||||
|  | ||||
|         result = RangeIndex(18, -2, -2)._min_fitting_element(1) | ||||
|         assert 2 == result | ||||
|  | ||||
|         result = RangeIndex(5, 0, -1)._min_fitting_element(1) | ||||
|         assert 1 == result | ||||
|  | ||||
|         big_num = 500000000000000000000000 | ||||
|  | ||||
|         result = RangeIndex(5, big_num * 2, 1)._min_fitting_element(big_num) | ||||
|         assert big_num == result | ||||
|  | ||||
|     def test_slice_specialised(self, simple_index): | ||||
|         index = simple_index | ||||
|         index.name = "foo" | ||||
|  | ||||
|         # scalar indexing | ||||
|         res = index[1] | ||||
|         expected = 2 | ||||
|         assert res == expected | ||||
|  | ||||
|         res = index[-1] | ||||
|         expected = 18 | ||||
|         assert res == expected | ||||
|  | ||||
|         # slicing | ||||
|         # slice value completion | ||||
|         index_slice = index[:] | ||||
|         expected = index | ||||
|         tm.assert_index_equal(index_slice, expected) | ||||
|  | ||||
|         # positive slice values | ||||
|         index_slice = index[7:10:2] | ||||
|         expected = Index([14, 18], name="foo") | ||||
|         tm.assert_index_equal(index_slice, expected, exact="equiv") | ||||
|  | ||||
|         # negative slice values | ||||
|         index_slice = index[-1:-5:-2] | ||||
|         expected = Index([18, 14], name="foo") | ||||
|         tm.assert_index_equal(index_slice, expected, exact="equiv") | ||||
|  | ||||
|         # stop overshoot | ||||
|         index_slice = index[2:100:4] | ||||
|         expected = Index([4, 12], name="foo") | ||||
|         tm.assert_index_equal(index_slice, expected, exact="equiv") | ||||
|  | ||||
|         # reverse | ||||
|         index_slice = index[::-1] | ||||
|         expected = Index(index.values[::-1], name="foo") | ||||
|         tm.assert_index_equal(index_slice, expected, exact="equiv") | ||||
|  | ||||
|         index_slice = index[-8::-1] | ||||
|         expected = Index([4, 2, 0], name="foo") | ||||
|         tm.assert_index_equal(index_slice, expected, exact="equiv") | ||||
|  | ||||
|         index_slice = index[-40::-1] | ||||
|         expected = Index(np.array([], dtype=np.int64), name="foo") | ||||
|         tm.assert_index_equal(index_slice, expected, exact="equiv") | ||||
|  | ||||
|         index_slice = index[40::-1] | ||||
|         expected = Index(index.values[40::-1], name="foo") | ||||
|         tm.assert_index_equal(index_slice, expected, exact="equiv") | ||||
|  | ||||
|         index_slice = index[10::-1] | ||||
|         expected = Index(index.values[::-1], name="foo") | ||||
|         tm.assert_index_equal(index_slice, expected, exact="equiv") | ||||
|  | ||||
|     @pytest.mark.parametrize("step", set(range(-5, 6)) - {0}) | ||||
|     def test_len_specialised(self, step): | ||||
|         # make sure that our len is the same as np.arange calc | ||||
|         start, stop = (0, 5) if step > 0 else (5, 0) | ||||
|  | ||||
|         arr = np.arange(start, stop, step) | ||||
|         index = RangeIndex(start, stop, step) | ||||
|         assert len(index) == len(arr) | ||||
|  | ||||
|         index = RangeIndex(stop, start, step) | ||||
|         assert len(index) == 0 | ||||
|  | ||||
|     @pytest.mark.parametrize( | ||||
|         "indices, expected", | ||||
|         [ | ||||
|             ([RangeIndex(1, 12, 5)], RangeIndex(1, 12, 5)), | ||||
|             ([RangeIndex(0, 6, 4)], RangeIndex(0, 6, 4)), | ||||
|             ([RangeIndex(1, 3), RangeIndex(3, 7)], RangeIndex(1, 7)), | ||||
|             ([RangeIndex(1, 5, 2), RangeIndex(5, 6)], RangeIndex(1, 6, 2)), | ||||
|             ([RangeIndex(1, 3, 2), RangeIndex(4, 7, 3)], RangeIndex(1, 7, 3)), | ||||
|             ([RangeIndex(-4, 3, 2), RangeIndex(4, 7, 2)], RangeIndex(-4, 7, 2)), | ||||
|             ([RangeIndex(-4, -8), RangeIndex(-8, -12)], RangeIndex(0, 0)), | ||||
|             ([RangeIndex(-4, -8), RangeIndex(3, -4)], RangeIndex(0, 0)), | ||||
|             ([RangeIndex(-4, -8), RangeIndex(3, 5)], RangeIndex(3, 5)), | ||||
|             ([RangeIndex(-4, -2), RangeIndex(3, 5)], Index([-4, -3, 3, 4])), | ||||
|             ([RangeIndex(-2), RangeIndex(3, 5)], RangeIndex(3, 5)), | ||||
|             ([RangeIndex(2), RangeIndex(2)], Index([0, 1, 0, 1])), | ||||
|             ([RangeIndex(2), RangeIndex(2, 5), RangeIndex(5, 8, 4)], RangeIndex(0, 6)), | ||||
|             ( | ||||
|                 [RangeIndex(2), RangeIndex(3, 5), RangeIndex(5, 8, 4)], | ||||
|                 Index([0, 1, 3, 4, 5]), | ||||
|             ), | ||||
|             ( | ||||
|                 [RangeIndex(-2, 2), RangeIndex(2, 5), RangeIndex(5, 8, 4)], | ||||
|                 RangeIndex(-2, 6), | ||||
|             ), | ||||
|             ([RangeIndex(3), Index([-1, 3, 15])], Index([0, 1, 2, -1, 3, 15])), | ||||
|             ([RangeIndex(3), Index([-1, 3.1, 15.0])], Index([0, 1, 2, -1, 3.1, 15.0])), | ||||
|             ([RangeIndex(3), Index(["a", None, 14])], Index([0, 1, 2, "a", None, 14])), | ||||
|             ([RangeIndex(3, 1), Index(["a", None, 14])], Index(["a", None, 14])), | ||||
|         ], | ||||
|     ) | ||||
|     def test_append(self, indices, expected): | ||||
|         # GH16212 | ||||
|         result = indices[0].append(indices[1:]) | ||||
|         tm.assert_index_equal(result, expected, exact=True) | ||||
|  | ||||
|         if len(indices) == 2: | ||||
|             # Append single item rather than list | ||||
|             result2 = indices[0].append(indices[1]) | ||||
|             tm.assert_index_equal(result2, expected, exact=True) | ||||
|  | ||||
|     def test_engineless_lookup(self): | ||||
|         # GH 16685 | ||||
|         # Standard lookup on RangeIndex should not require the engine to be | ||||
|         # created | ||||
|         idx = RangeIndex(2, 10, 3) | ||||
|  | ||||
|         assert idx.get_loc(5) == 1 | ||||
|         tm.assert_numpy_array_equal( | ||||
|             idx.get_indexer([2, 8]), ensure_platform_int(np.array([0, 2])) | ||||
|         ) | ||||
|         with pytest.raises(KeyError, match="3"): | ||||
|             idx.get_loc(3) | ||||
|  | ||||
|         assert "_engine" not in idx._cache | ||||
|  | ||||
|         # Different types of scalars can be excluded immediately, no need to | ||||
|         #  use the _engine | ||||
|         with pytest.raises(KeyError, match="'a'"): | ||||
|             idx.get_loc("a") | ||||
|  | ||||
|         assert "_engine" not in idx._cache | ||||
|  | ||||
|     def test_format_empty(self): | ||||
|         # GH35712 | ||||
|         empty_idx = RangeIndex(0) | ||||
|         msg = r"RangeIndex\.format is deprecated" | ||||
|         with tm.assert_produces_warning(FutureWarning, match=msg): | ||||
|             assert empty_idx.format() == [] | ||||
|         with tm.assert_produces_warning(FutureWarning, match=msg): | ||||
|             assert empty_idx.format(name=True) == [""] | ||||
|  | ||||
|     @pytest.mark.parametrize( | ||||
|         "ri", | ||||
|         [ | ||||
|             RangeIndex(0, -1, -1), | ||||
|             RangeIndex(0, 1, 1), | ||||
|             RangeIndex(1, 3, 2), | ||||
|             RangeIndex(0, -1, -2), | ||||
|             RangeIndex(-3, -5, -2), | ||||
|         ], | ||||
|     ) | ||||
|     def test_append_len_one(self, ri): | ||||
|         # GH39401 | ||||
|         result = ri.append([]) | ||||
|         tm.assert_index_equal(result, ri, exact=True) | ||||
|  | ||||
|     @pytest.mark.parametrize("base", [RangeIndex(0, 2), Index([0, 1])]) | ||||
|     def test_isin_range(self, base): | ||||
|         # GH#41151 | ||||
|         values = RangeIndex(0, 1) | ||||
|         result = base.isin(values) | ||||
|         expected = np.array([True, False]) | ||||
|         tm.assert_numpy_array_equal(result, expected) | ||||
|  | ||||
|     def test_sort_values_key(self): | ||||
|         # GH#43666, GH#52764 | ||||
|         sort_order = {8: 2, 6: 0, 4: 8, 2: 10, 0: 12} | ||||
|         values = RangeIndex(0, 10, 2) | ||||
|         result = values.sort_values(key=lambda x: x.map(sort_order)) | ||||
|         expected = Index([6, 8, 4, 2, 0], dtype="int64") | ||||
|         tm.assert_index_equal(result, expected, check_exact=True) | ||||
|  | ||||
|         # check this matches the Series.sort_values behavior | ||||
|         ser = values.to_series() | ||||
|         result2 = ser.sort_values(key=lambda x: x.map(sort_order)) | ||||
|         tm.assert_series_equal(result2, expected.to_series(), check_exact=True) | ||||
|  | ||||
|     def test_range_index_rsub_by_const(self): | ||||
|         # GH#53255 | ||||
|         result = 3 - RangeIndex(0, 4, 1) | ||||
|         expected = RangeIndex(3, -1, -1) | ||||
|         tm.assert_index_equal(result, expected) | ||||
| @ -0,0 +1,493 @@ | ||||
| from datetime import ( | ||||
|     datetime, | ||||
|     timedelta, | ||||
| ) | ||||
|  | ||||
| from hypothesis import ( | ||||
|     assume, | ||||
|     given, | ||||
|     strategies as st, | ||||
| ) | ||||
| import numpy as np | ||||
| import pytest | ||||
|  | ||||
| from pandas import ( | ||||
|     Index, | ||||
|     RangeIndex, | ||||
| ) | ||||
| import pandas._testing as tm | ||||
|  | ||||
|  | ||||
| class TestRangeIndexSetOps: | ||||
|     @pytest.mark.parametrize("dtype", [None, "int64", "uint64"]) | ||||
|     def test_intersection_mismatched_dtype(self, dtype): | ||||
|         # check that we cast to float, not object | ||||
|         index = RangeIndex(start=0, stop=20, step=2, name="foo") | ||||
|         index = Index(index, dtype=dtype) | ||||
|  | ||||
|         flt = index.astype(np.float64) | ||||
|  | ||||
|         # bc index.equals(flt), we go through fastpath and get RangeIndex back | ||||
|         result = index.intersection(flt) | ||||
|         tm.assert_index_equal(result, index, exact=True) | ||||
|  | ||||
|         result = flt.intersection(index) | ||||
|         tm.assert_index_equal(result, flt, exact=True) | ||||
|  | ||||
|         # neither empty, not-equals | ||||
|         result = index.intersection(flt[1:]) | ||||
|         tm.assert_index_equal(result, flt[1:], exact=True) | ||||
|  | ||||
|         result = flt[1:].intersection(index) | ||||
|         tm.assert_index_equal(result, flt[1:], exact=True) | ||||
|  | ||||
|         # empty other | ||||
|         result = index.intersection(flt[:0]) | ||||
|         tm.assert_index_equal(result, flt[:0], exact=True) | ||||
|  | ||||
|         result = flt[:0].intersection(index) | ||||
|         tm.assert_index_equal(result, flt[:0], exact=True) | ||||
|  | ||||
|     def test_intersection_empty(self, sort, names): | ||||
|         # name retention on empty intersections | ||||
|         index = RangeIndex(start=0, stop=20, step=2, name=names[0]) | ||||
|  | ||||
|         # empty other | ||||
|         result = index.intersection(index[:0].rename(names[1]), sort=sort) | ||||
|         tm.assert_index_equal(result, index[:0].rename(names[2]), exact=True) | ||||
|  | ||||
|         # empty self | ||||
|         result = index[:0].intersection(index.rename(names[1]), sort=sort) | ||||
|         tm.assert_index_equal(result, index[:0].rename(names[2]), exact=True) | ||||
|  | ||||
|     def test_intersection(self, sort): | ||||
|         # intersect with Index with dtype int64 | ||||
|         index = RangeIndex(start=0, stop=20, step=2) | ||||
|         other = Index(np.arange(1, 6)) | ||||
|         result = index.intersection(other, sort=sort) | ||||
|         expected = Index(np.sort(np.intersect1d(index.values, other.values))) | ||||
|         tm.assert_index_equal(result, expected) | ||||
|  | ||||
|         result = other.intersection(index, sort=sort) | ||||
|         expected = Index( | ||||
|             np.sort(np.asarray(np.intersect1d(index.values, other.values))) | ||||
|         ) | ||||
|         tm.assert_index_equal(result, expected) | ||||
|  | ||||
|         # intersect with increasing RangeIndex | ||||
|         other = RangeIndex(1, 6) | ||||
|         result = index.intersection(other, sort=sort) | ||||
|         expected = Index(np.sort(np.intersect1d(index.values, other.values))) | ||||
|         tm.assert_index_equal(result, expected, exact="equiv") | ||||
|  | ||||
|         # intersect with decreasing RangeIndex | ||||
|         other = RangeIndex(5, 0, -1) | ||||
|         result = index.intersection(other, sort=sort) | ||||
|         expected = Index(np.sort(np.intersect1d(index.values, other.values))) | ||||
|         tm.assert_index_equal(result, expected, exact="equiv") | ||||
|  | ||||
|         # reversed (GH 17296) | ||||
|         result = other.intersection(index, sort=sort) | ||||
|         tm.assert_index_equal(result, expected, exact="equiv") | ||||
|  | ||||
|         # GH 17296: intersect two decreasing RangeIndexes | ||||
|         first = RangeIndex(10, -2, -2) | ||||
|         other = RangeIndex(5, -4, -1) | ||||
|         expected = first.astype(int).intersection(other.astype(int), sort=sort) | ||||
|         result = first.intersection(other, sort=sort).astype(int) | ||||
|         tm.assert_index_equal(result, expected) | ||||
|  | ||||
|         # reversed | ||||
|         result = other.intersection(first, sort=sort).astype(int) | ||||
|         tm.assert_index_equal(result, expected) | ||||
|  | ||||
|         index = RangeIndex(5, name="foo") | ||||
|  | ||||
|         # intersect of non-overlapping indices | ||||
|         other = RangeIndex(5, 10, 1, name="foo") | ||||
|         result = index.intersection(other, sort=sort) | ||||
|         expected = RangeIndex(0, 0, 1, name="foo") | ||||
|         tm.assert_index_equal(result, expected) | ||||
|  | ||||
|         other = RangeIndex(-1, -5, -1) | ||||
|         result = index.intersection(other, sort=sort) | ||||
|         expected = RangeIndex(0, 0, 1) | ||||
|         tm.assert_index_equal(result, expected) | ||||
|  | ||||
|         # intersection of empty indices | ||||
|         other = RangeIndex(0, 0, 1) | ||||
|         result = index.intersection(other, sort=sort) | ||||
|         expected = RangeIndex(0, 0, 1) | ||||
|         tm.assert_index_equal(result, expected) | ||||
|  | ||||
|         result = other.intersection(index, sort=sort) | ||||
|         tm.assert_index_equal(result, expected) | ||||
|  | ||||
|     def test_intersection_non_overlapping_gcd(self, sort, names): | ||||
|         # intersection of non-overlapping values based on start value and gcd | ||||
|         index = RangeIndex(1, 10, 2, name=names[0]) | ||||
|         other = RangeIndex(0, 10, 4, name=names[1]) | ||||
|         result = index.intersection(other, sort=sort) | ||||
|         expected = RangeIndex(0, 0, 1, name=names[2]) | ||||
|         tm.assert_index_equal(result, expected) | ||||
|  | ||||
|     def test_union_noncomparable(self, sort): | ||||
|         # corner case, Index with non-int64 dtype | ||||
|         index = RangeIndex(start=0, stop=20, step=2) | ||||
|         other = Index([datetime.now() + timedelta(i) for i in range(4)], dtype=object) | ||||
|         result = index.union(other, sort=sort) | ||||
|         expected = Index(np.concatenate((index, other))) | ||||
|         tm.assert_index_equal(result, expected) | ||||
|  | ||||
|         result = other.union(index, sort=sort) | ||||
|         expected = Index(np.concatenate((other, index))) | ||||
|         tm.assert_index_equal(result, expected) | ||||
|  | ||||
|     @pytest.mark.parametrize( | ||||
|         "idx1, idx2, expected_sorted, expected_notsorted", | ||||
|         [ | ||||
|             ( | ||||
|                 RangeIndex(0, 10, 1), | ||||
|                 RangeIndex(0, 10, 1), | ||||
|                 RangeIndex(0, 10, 1), | ||||
|                 RangeIndex(0, 10, 1), | ||||
|             ), | ||||
|             ( | ||||
|                 RangeIndex(0, 10, 1), | ||||
|                 RangeIndex(5, 20, 1), | ||||
|                 RangeIndex(0, 20, 1), | ||||
|                 RangeIndex(0, 20, 1), | ||||
|             ), | ||||
|             ( | ||||
|                 RangeIndex(0, 10, 1), | ||||
|                 RangeIndex(10, 20, 1), | ||||
|                 RangeIndex(0, 20, 1), | ||||
|                 RangeIndex(0, 20, 1), | ||||
|             ), | ||||
|             ( | ||||
|                 RangeIndex(0, -10, -1), | ||||
|                 RangeIndex(0, -10, -1), | ||||
|                 RangeIndex(0, -10, -1), | ||||
|                 RangeIndex(0, -10, -1), | ||||
|             ), | ||||
|             ( | ||||
|                 RangeIndex(0, -10, -1), | ||||
|                 RangeIndex(-10, -20, -1), | ||||
|                 RangeIndex(-19, 1, 1), | ||||
|                 RangeIndex(0, -20, -1), | ||||
|             ), | ||||
|             ( | ||||
|                 RangeIndex(0, 10, 2), | ||||
|                 RangeIndex(1, 10, 2), | ||||
|                 RangeIndex(0, 10, 1), | ||||
|                 Index(list(range(0, 10, 2)) + list(range(1, 10, 2))), | ||||
|             ), | ||||
|             ( | ||||
|                 RangeIndex(0, 11, 2), | ||||
|                 RangeIndex(1, 12, 2), | ||||
|                 RangeIndex(0, 12, 1), | ||||
|                 Index(list(range(0, 11, 2)) + list(range(1, 12, 2))), | ||||
|             ), | ||||
|             ( | ||||
|                 RangeIndex(0, 21, 4), | ||||
|                 RangeIndex(-2, 24, 4), | ||||
|                 RangeIndex(-2, 24, 2), | ||||
|                 Index(list(range(0, 21, 4)) + list(range(-2, 24, 4))), | ||||
|             ), | ||||
|             ( | ||||
|                 RangeIndex(0, -20, -2), | ||||
|                 RangeIndex(-1, -21, -2), | ||||
|                 RangeIndex(-19, 1, 1), | ||||
|                 Index(list(range(0, -20, -2)) + list(range(-1, -21, -2))), | ||||
|             ), | ||||
|             ( | ||||
|                 RangeIndex(0, 100, 5), | ||||
|                 RangeIndex(0, 100, 20), | ||||
|                 RangeIndex(0, 100, 5), | ||||
|                 RangeIndex(0, 100, 5), | ||||
|             ), | ||||
|             ( | ||||
|                 RangeIndex(0, -100, -5), | ||||
|                 RangeIndex(5, -100, -20), | ||||
|                 RangeIndex(-95, 10, 5), | ||||
|                 Index(list(range(0, -100, -5)) + [5]), | ||||
|             ), | ||||
|             ( | ||||
|                 RangeIndex(0, -11, -1), | ||||
|                 RangeIndex(1, -12, -4), | ||||
|                 RangeIndex(-11, 2, 1), | ||||
|                 Index(list(range(0, -11, -1)) + [1, -11]), | ||||
|             ), | ||||
|             (RangeIndex(0), RangeIndex(0), RangeIndex(0), RangeIndex(0)), | ||||
|             ( | ||||
|                 RangeIndex(0, -10, -2), | ||||
|                 RangeIndex(0), | ||||
|                 RangeIndex(0, -10, -2), | ||||
|                 RangeIndex(0, -10, -2), | ||||
|             ), | ||||
|             ( | ||||
|                 RangeIndex(0, 100, 2), | ||||
|                 RangeIndex(100, 150, 200), | ||||
|                 RangeIndex(0, 102, 2), | ||||
|                 RangeIndex(0, 102, 2), | ||||
|             ), | ||||
|             ( | ||||
|                 RangeIndex(0, -100, -2), | ||||
|                 RangeIndex(-100, 50, 102), | ||||
|                 RangeIndex(-100, 4, 2), | ||||
|                 Index(list(range(0, -100, -2)) + [-100, 2]), | ||||
|             ), | ||||
|             ( | ||||
|                 RangeIndex(0, -100, -1), | ||||
|                 RangeIndex(0, -50, -3), | ||||
|                 RangeIndex(-99, 1, 1), | ||||
|                 RangeIndex(0, -100, -1), | ||||
|             ), | ||||
|             ( | ||||
|                 RangeIndex(0, 1, 1), | ||||
|                 RangeIndex(5, 6, 10), | ||||
|                 RangeIndex(0, 6, 5), | ||||
|                 RangeIndex(0, 10, 5), | ||||
|             ), | ||||
|             ( | ||||
|                 RangeIndex(0, 10, 5), | ||||
|                 RangeIndex(-5, -6, -20), | ||||
|                 RangeIndex(-5, 10, 5), | ||||
|                 Index([0, 5, -5]), | ||||
|             ), | ||||
|             ( | ||||
|                 RangeIndex(0, 3, 1), | ||||
|                 RangeIndex(4, 5, 1), | ||||
|                 Index([0, 1, 2, 4]), | ||||
|                 Index([0, 1, 2, 4]), | ||||
|             ), | ||||
|             ( | ||||
|                 RangeIndex(0, 10, 1), | ||||
|                 Index([], dtype=np.int64), | ||||
|                 RangeIndex(0, 10, 1), | ||||
|                 RangeIndex(0, 10, 1), | ||||
|             ), | ||||
|             ( | ||||
|                 RangeIndex(0), | ||||
|                 Index([1, 5, 6]), | ||||
|                 Index([1, 5, 6]), | ||||
|                 Index([1, 5, 6]), | ||||
|             ), | ||||
|             # GH 43885 | ||||
|             ( | ||||
|                 RangeIndex(0, 10), | ||||
|                 RangeIndex(0, 5), | ||||
|                 RangeIndex(0, 10), | ||||
|                 RangeIndex(0, 10), | ||||
|             ), | ||||
|         ], | ||||
|         ids=lambda x: repr(x) if isinstance(x, RangeIndex) else x, | ||||
|     ) | ||||
|     def test_union_sorted(self, idx1, idx2, expected_sorted, expected_notsorted): | ||||
|         res1 = idx1.union(idx2, sort=None) | ||||
|         tm.assert_index_equal(res1, expected_sorted, exact=True) | ||||
|  | ||||
|         res1 = idx1.union(idx2, sort=False) | ||||
|         tm.assert_index_equal(res1, expected_notsorted, exact=True) | ||||
|  | ||||
|         res2 = idx2.union(idx1, sort=None) | ||||
|         res3 = Index(idx1._values, name=idx1.name).union(idx2, sort=None) | ||||
|         tm.assert_index_equal(res2, expected_sorted, exact=True) | ||||
|         tm.assert_index_equal(res3, expected_sorted, exact="equiv") | ||||
|  | ||||
|     def test_union_same_step_misaligned(self): | ||||
|         # GH#44019 | ||||
|         left = RangeIndex(range(0, 20, 4)) | ||||
|         right = RangeIndex(range(1, 21, 4)) | ||||
|  | ||||
|         result = left.union(right) | ||||
|         expected = Index([0, 1, 4, 5, 8, 9, 12, 13, 16, 17]) | ||||
|         tm.assert_index_equal(result, expected, exact=True) | ||||
|  | ||||
|     def test_difference(self): | ||||
|         # GH#12034 Cases where we operate against another RangeIndex and may | ||||
|         #  get back another RangeIndex | ||||
|         obj = RangeIndex.from_range(range(1, 10), name="foo") | ||||
|  | ||||
|         result = obj.difference(obj) | ||||
|         expected = RangeIndex.from_range(range(0), name="foo") | ||||
|         tm.assert_index_equal(result, expected, exact=True) | ||||
|  | ||||
|         result = obj.difference(expected.rename("bar")) | ||||
|         tm.assert_index_equal(result, obj.rename(None), exact=True) | ||||
|  | ||||
|         result = obj.difference(obj[:3]) | ||||
|         tm.assert_index_equal(result, obj[3:], exact=True) | ||||
|  | ||||
|         result = obj.difference(obj[-3:]) | ||||
|         tm.assert_index_equal(result, obj[:-3], exact=True) | ||||
|  | ||||
|         # Flipping the step of 'other' doesn't affect the result, but | ||||
|         #  flipping the stepof 'self' does when sort=None | ||||
|         result = obj[::-1].difference(obj[-3:]) | ||||
|         tm.assert_index_equal(result, obj[:-3], exact=True) | ||||
|  | ||||
|         result = obj[::-1].difference(obj[-3:], sort=False) | ||||
|         tm.assert_index_equal(result, obj[:-3][::-1], exact=True) | ||||
|  | ||||
|         result = obj[::-1].difference(obj[-3:][::-1]) | ||||
|         tm.assert_index_equal(result, obj[:-3], exact=True) | ||||
|  | ||||
|         result = obj[::-1].difference(obj[-3:][::-1], sort=False) | ||||
|         tm.assert_index_equal(result, obj[:-3][::-1], exact=True) | ||||
|  | ||||
|         result = obj.difference(obj[2:6]) | ||||
|         expected = Index([1, 2, 7, 8, 9], name="foo") | ||||
|         tm.assert_index_equal(result, expected, exact=True) | ||||
|  | ||||
|     def test_difference_sort(self): | ||||
|         # GH#44085 ensure we respect the sort keyword | ||||
|  | ||||
|         idx = Index(range(4))[::-1] | ||||
|         other = Index(range(3, 4)) | ||||
|  | ||||
|         result = idx.difference(other) | ||||
|         expected = Index(range(3)) | ||||
|         tm.assert_index_equal(result, expected, exact=True) | ||||
|  | ||||
|         result = idx.difference(other, sort=False) | ||||
|         expected = expected[::-1] | ||||
|         tm.assert_index_equal(result, expected, exact=True) | ||||
|  | ||||
|         # case where the intersection is empty | ||||
|         other = range(10, 12) | ||||
|         result = idx.difference(other, sort=None) | ||||
|         expected = idx[::-1] | ||||
|         tm.assert_index_equal(result, expected, exact=True) | ||||
|  | ||||
|     def test_difference_mismatched_step(self): | ||||
|         obj = RangeIndex.from_range(range(1, 10), name="foo") | ||||
|  | ||||
|         result = obj.difference(obj[::2]) | ||||
|         expected = obj[1::2] | ||||
|         tm.assert_index_equal(result, expected, exact=True) | ||||
|  | ||||
|         result = obj[::-1].difference(obj[::2], sort=False) | ||||
|         tm.assert_index_equal(result, expected[::-1], exact=True) | ||||
|  | ||||
|         result = obj.difference(obj[1::2]) | ||||
|         expected = obj[::2] | ||||
|         tm.assert_index_equal(result, expected, exact=True) | ||||
|  | ||||
|         result = obj[::-1].difference(obj[1::2], sort=False) | ||||
|         tm.assert_index_equal(result, expected[::-1], exact=True) | ||||
|  | ||||
|     def test_difference_interior_overlap_endpoints_preserved(self): | ||||
|         left = RangeIndex(range(4)) | ||||
|         right = RangeIndex(range(1, 3)) | ||||
|  | ||||
|         result = left.difference(right) | ||||
|         expected = RangeIndex(0, 4, 3) | ||||
|         assert expected.tolist() == [0, 3] | ||||
|         tm.assert_index_equal(result, expected, exact=True) | ||||
|  | ||||
|     def test_difference_endpoints_overlap_interior_preserved(self): | ||||
|         left = RangeIndex(-8, 20, 7) | ||||
|         right = RangeIndex(13, -9, -3) | ||||
|  | ||||
|         result = left.difference(right) | ||||
|         expected = RangeIndex(-1, 13, 7) | ||||
|         assert expected.tolist() == [-1, 6] | ||||
|         tm.assert_index_equal(result, expected, exact=True) | ||||
|  | ||||
|     def test_difference_interior_non_preserving(self): | ||||
|         # case with intersection of length 1 but RangeIndex is not preserved | ||||
|         idx = Index(range(10)) | ||||
|  | ||||
|         other = idx[3:4] | ||||
|         result = idx.difference(other) | ||||
|         expected = Index([0, 1, 2, 4, 5, 6, 7, 8, 9]) | ||||
|         tm.assert_index_equal(result, expected, exact=True) | ||||
|  | ||||
|         # case with other.step / self.step > 2 | ||||
|         other = idx[::3] | ||||
|         result = idx.difference(other) | ||||
|         expected = Index([1, 2, 4, 5, 7, 8]) | ||||
|         tm.assert_index_equal(result, expected, exact=True) | ||||
|  | ||||
|         # cases with only reaching one end of left | ||||
|         obj = Index(range(20)) | ||||
|         other = obj[:10:2] | ||||
|         result = obj.difference(other) | ||||
|         expected = Index([1, 3, 5, 7, 9] + list(range(10, 20))) | ||||
|         tm.assert_index_equal(result, expected, exact=True) | ||||
|  | ||||
|         other = obj[1:11:2] | ||||
|         result = obj.difference(other) | ||||
|         expected = Index([0, 2, 4, 6, 8, 10] + list(range(11, 20))) | ||||
|         tm.assert_index_equal(result, expected, exact=True) | ||||
|  | ||||
|     def test_symmetric_difference(self): | ||||
|         # GH#12034 Cases where we operate against another RangeIndex and may | ||||
|         #  get back another RangeIndex | ||||
|         left = RangeIndex.from_range(range(1, 10), name="foo") | ||||
|  | ||||
|         result = left.symmetric_difference(left) | ||||
|         expected = RangeIndex.from_range(range(0), name="foo") | ||||
|         tm.assert_index_equal(result, expected) | ||||
|  | ||||
|         result = left.symmetric_difference(expected.rename("bar")) | ||||
|         tm.assert_index_equal(result, left.rename(None)) | ||||
|  | ||||
|         result = left[:-2].symmetric_difference(left[2:]) | ||||
|         expected = Index([1, 2, 8, 9], name="foo") | ||||
|         tm.assert_index_equal(result, expected, exact=True) | ||||
|  | ||||
|         right = RangeIndex.from_range(range(10, 15)) | ||||
|  | ||||
|         result = left.symmetric_difference(right) | ||||
|         expected = RangeIndex.from_range(range(1, 15)) | ||||
|         tm.assert_index_equal(result, expected) | ||||
|  | ||||
|         result = left.symmetric_difference(right[1:]) | ||||
|         expected = Index([1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 12, 13, 14]) | ||||
|         tm.assert_index_equal(result, expected, exact=True) | ||||
|  | ||||
|  | ||||
| def assert_range_or_not_is_rangelike(index): | ||||
|     """ | ||||
|     Check that we either have a RangeIndex or that this index *cannot* | ||||
|     be represented as a RangeIndex. | ||||
|     """ | ||||
|     if not isinstance(index, RangeIndex) and len(index) > 0: | ||||
|         diff = index[:-1] - index[1:] | ||||
|         assert not (diff == diff[0]).all() | ||||
|  | ||||
|  | ||||
| @given( | ||||
|     st.integers(-20, 20), | ||||
|     st.integers(-20, 20), | ||||
|     st.integers(-20, 20), | ||||
|     st.integers(-20, 20), | ||||
|     st.integers(-20, 20), | ||||
|     st.integers(-20, 20), | ||||
| ) | ||||
| def test_range_difference(start1, stop1, step1, start2, stop2, step2): | ||||
|     # test that | ||||
|     #  a) we match Index[int64].difference and | ||||
|     #  b) we return RangeIndex whenever it is possible to do so. | ||||
|     assume(step1 != 0) | ||||
|     assume(step2 != 0) | ||||
|  | ||||
|     left = RangeIndex(start1, stop1, step1) | ||||
|     right = RangeIndex(start2, stop2, step2) | ||||
|  | ||||
|     result = left.difference(right, sort=None) | ||||
|     assert_range_or_not_is_rangelike(result) | ||||
|  | ||||
|     left_int64 = Index(left.to_numpy()) | ||||
|     right_int64 = Index(right.to_numpy()) | ||||
|  | ||||
|     alt = left_int64.difference(right_int64, sort=None) | ||||
|     tm.assert_index_equal(result, alt, exact="equiv") | ||||
|  | ||||
|     result = left.difference(right, sort=False) | ||||
|     assert_range_or_not_is_rangelike(result) | ||||
|  | ||||
|     alt = left_int64.difference(right_int64, sort=False) | ||||
|     tm.assert_index_equal(result, alt, exact="equiv") | ||||
		Reference in New Issue
	
	Block a user