def test_is_monotonic(self): index = RangeIndex(0, 20, 2) assert index.is_monotonic 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 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 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 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 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_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_same_step_misaligned(self): # GH#44019 left = RangeIndex(range(0, 20, 4)) right = RangeIndex(range(1, 21, 4)) result = left.union(right) expected = Int64Index([0, 1, 4, 5, 8, 9, 12, 13, 16, 17]) 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_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_nbytes(self): # memory savings vs int index idx = RangeIndex(0, 1000) assert idx.nbytes < Int64Index(idx._values).nbytes / 10 # constant memory usage i2 = RangeIndex(0, 10) assert idx.nbytes == i2.nbytes
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
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_intersection_mismatched_dtype(self, klass): # check that we cast to float, not object index = RangeIndex(start=0, stop=20, step=2, name="foo") index = klass(index) 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_sort_values_key(self): # GH#43666 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([4, 8, 6, 0, 2], dtype="int64") tm.assert_index_equal(result, expected, check_exact=True)
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_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_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 = Float64Index([0, np.nan, 1, 2, 3, 4]) 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_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_equals_range(self): equiv_pairs = [ (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)), ] for left, right in equiv_pairs: assert left.equals(right) assert right.equals(left)
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_range_float_union_dtype(self): # https://github.com/pandas-dev/pandas/issues/26778 index = RangeIndex(start=0, stop=3) other = Float64Index([0.5, 1.5]) result = index.union(other) expected = Float64Index([0.0, 0.5, 1, 1.5, 2.0]) tm.assert_index_equal(result, expected) result = other.union(index) tm.assert_index_equal(result, expected)
def test_delete_not_preserving_rangeindex(self): idx = RangeIndex(0, 6, 1) loc = [0, 3, 5] result = idx.delete(loc) expected = Int64Index([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) i_view = i.view(RangeIndex) tm.assert_index_equal(i, i_view)
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_range_difference(start1, stop1, step1, start2, stop2, step2): # test that # a) we match Int64Index.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) alt = Int64Index(left).difference(Int64Index(right), sort=None) tm.assert_index_equal(result, alt, exact="equiv") result = left.difference(right, sort=False) assert_range_or_not_is_rangelike(result) alt = Int64Index(left).difference(Int64Index(right), sort=False) tm.assert_index_equal(result, alt, exact="equiv")
def test_union_noncomparable(self, sort): # corner case, non-Int64Index 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)
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_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 read(self, nrows=None): nrows = validate_integer("nrows", nrows) index, columns, col_dict = self._engine.read(nrows) if index is None: if col_dict: # Any column is actually fine: new_rows = len(next(iter(col_dict.values()))) index = RangeIndex(self._currow, self._currow + new_rows) else: new_rows = 0 else: new_rows = len(index) df = DataFrame(col_dict, columns=columns, index=index) self._currow += new_rows if self.squeeze and len(df.columns) == 1: return df[df.columns[0]].copy() return df
def test_intersection(self, sort): # intersect with Int64Index 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_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_slice_keep_name(self): idx = RangeIndex(1, 2, name="asdf") assert idx.name == idx[1:].name
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)
class TestRangeIndexSetOps: @pytest.mark.parametrize("klass", [RangeIndex, Int64Index, UInt64Index]) def test_intersection_mismatched_dtype(self, klass): # check that we cast to float, not object index = RangeIndex(start=0, stop=20, step=2, name="foo") index = klass(index) 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 Int64Index 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, non-Int64Index 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.fixture(params=[ ( 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), Int64Index(range(20)), ), ( RangeIndex(0, 10, 1), RangeIndex(10, 20, 1), RangeIndex(0, 20, 1), Int64Index(range(20)), ), ( 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), Int64Index(range(0, -20, -1)), ), ( RangeIndex(0, 10, 2), RangeIndex(1, 10, 2), RangeIndex(0, 10, 1), Int64Index(list(range(0, 10, 2)) + list(range(1, 10, 2))), ), ( RangeIndex(0, 11, 2), RangeIndex(1, 12, 2), RangeIndex(0, 12, 1), Int64Index(list(range(0, 11, 2)) + list(range(1, 12, 2))), ), ( RangeIndex(0, 21, 4), RangeIndex(-2, 24, 4), RangeIndex(-2, 24, 2), Int64Index(list(range(0, 21, 4)) + list(range(-2, 24, 4))), ), ( RangeIndex(0, -20, -2), RangeIndex(-1, -21, -2), RangeIndex(-19, 1, 1), Int64Index(list(range(0, -20, -2)) + list(range(-1, -21, -2))), ), ( RangeIndex(0, 100, 5), RangeIndex(0, 100, 20), RangeIndex(0, 100, 5), Int64Index(range(0, 100, 5)), ), ( RangeIndex(0, -100, -5), RangeIndex(5, -100, -20), RangeIndex(-95, 10, 5), Int64Index(list(range(0, -100, -5)) + [5]), ), ( RangeIndex(0, -11, -1), RangeIndex(1, -12, -4), RangeIndex(-11, 2, 1), Int64Index(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), Int64Index(range(0, 102, 2)), ), ( RangeIndex(0, -100, -2), RangeIndex(-100, 50, 102), RangeIndex(-100, 4, 2), Int64Index(list(range(0, -100, -2)) + [-100, 2]), ), ( RangeIndex(0, -100, -1), RangeIndex(0, -50, -3), RangeIndex(-99, 1, 1), Int64Index(list(range(0, -100, -1))), ), ( RangeIndex(0, 1, 1), RangeIndex(5, 6, 10), RangeIndex(0, 6, 5), Int64Index([0, 5]), ), ( RangeIndex(0, 10, 5), RangeIndex(-5, -6, -20), RangeIndex(-5, 10, 5), Int64Index([0, 5, -5]), ), ( RangeIndex(0, 3, 1), RangeIndex(4, 5, 1), Int64Index([0, 1, 2, 4]), Int64Index([0, 1, 2, 4]), ), ( RangeIndex(0, 10, 1), Int64Index([]), RangeIndex(0, 10, 1), RangeIndex(0, 10, 1), ), ( RangeIndex(0), Int64Index([1, 5, 6]), Int64Index([1, 5, 6]), Int64Index([1, 5, 6]), ), ]) def unions(self, request): """Inputs and expected outputs for RangeIndex.union tests""" return request.param def test_union_sorted(self, unions): idx1, idx2, expected_sorted, expected_notsorted = unions 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 = Int64Index(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 = Int64Index([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 = Int64Index([1, 2, 7, 8, 9], name="foo") tm.assert_index_equal(result, expected) 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 = Int64Index([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 = Int64Index([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 = Int64Index([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 = Int64Index([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 = Int64Index([1, 2, 8, 9], name="foo") tm.assert_index_equal(result, expected) 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 = Int64Index([1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 12, 13, 14]) tm.assert_index_equal(result, expected)