diff --git a/pandas/tests/indexes/interval/test_base.py b/pandas/tests/indexes/interval/test_base.py new file mode 100644 index 0000000000000..b2cb29dafac09 --- /dev/null +++ b/pandas/tests/indexes/interval/test_base.py @@ -0,0 +1,82 @@ +import numpy as np +import pytest + +from pandas import IntervalIndex, Series, date_range +from pandas.tests.indexes.common import Base +import pandas.util.testing as tm + + +class TestBase(Base): + """ + Tests specific to the shared common index tests; unrelated tests should be placed + in test_interval.py or the specific test file (e.g. test_astype.py) + """ + + _holder = IntervalIndex + + def setup_method(self, method): + self.index = IntervalIndex.from_arrays([0, 1], [1, 2]) + self.index_with_nan = IntervalIndex.from_tuples([(0, 1), np.nan, (1, 2)]) + self.indices = dict(intervalIndex=tm.makeIntervalIndex(10)) + + def create_index(self, closed="right"): + return IntervalIndex.from_breaks(range(11), closed=closed) + + def test_equals(self, closed): + expected = IntervalIndex.from_breaks(np.arange(5), closed=closed) + assert expected.equals(expected) + assert expected.equals(expected.copy()) + + assert not expected.equals(expected.astype(object)) + assert not expected.equals(np.array(expected)) + assert not expected.equals(list(expected)) + + assert not expected.equals([1, 2]) + assert not expected.equals(np.array([1, 2])) + assert not expected.equals(date_range("20130101", periods=2)) + + expected_name1 = IntervalIndex.from_breaks( + np.arange(5), closed=closed, name="foo" + ) + expected_name2 = IntervalIndex.from_breaks( + np.arange(5), closed=closed, name="bar" + ) + assert expected.equals(expected_name1) + assert expected_name1.equals(expected_name2) + + for other_closed in {"left", "right", "both", "neither"} - {closed}: + expected_other_closed = IntervalIndex.from_breaks( + np.arange(5), closed=other_closed + ) + assert not expected.equals(expected_other_closed) + + def test_repr_max_seq_item_setting(self): + # override base test: not a valid repr as we use interval notation + pass + + def test_repr_roundtrip(self): + # override base test: not a valid repr as we use interval notation + pass + + def test_take(self, closed): + index = self.create_index(closed=closed) + + result = index.take(range(10)) + tm.assert_index_equal(result, index) + + result = index.take([0, 0, 1]) + expected = IntervalIndex.from_arrays([0, 0, 1], [1, 1, 2], closed=closed) + tm.assert_index_equal(result, expected) + + @pytest.mark.parametrize("klass", [list, tuple, np.array, Series]) + def test_where(self, closed, klass): + idx = self.create_index(closed=closed) + cond = [True] * len(idx) + expected = idx + result = expected.where(klass(cond)) + tm.assert_index_equal(result, expected) + + cond = [False] + [True] * len(idx[1:]) + expected = IntervalIndex([np.nan] + idx[1:].tolist()) + result = idx.where(klass(cond)) + tm.assert_index_equal(result, expected) diff --git a/pandas/tests/indexes/interval/test_formats.py b/pandas/tests/indexes/interval/test_formats.py new file mode 100644 index 0000000000000..dcc0c818182ab --- /dev/null +++ b/pandas/tests/indexes/interval/test_formats.py @@ -0,0 +1,78 @@ +import numpy as np +import pytest + +from pandas import DataFrame, IntervalIndex, Series, Timedelta, Timestamp +import pandas.util.testing as tm + + +class TestIntervalIndexRendering: + def test_frame_repr(self): + # https://github.com/pandas-dev/pandas/pull/24134/files + df = DataFrame( + {"A": [1, 2, 3, 4]}, index=IntervalIndex.from_breaks([0, 1, 2, 3, 4]) + ) + result = repr(df) + expected = " A\n(0, 1] 1\n(1, 2] 2\n(2, 3] 3\n(3, 4] 4" + assert result == expected + + @pytest.mark.parametrize( + "constructor,expected", + [ + ( + Series, + ( + "(0.0, 1.0] a\n" + "NaN b\n" + "(2.0, 3.0] c\n" + "dtype: object" + ), + ), + (DataFrame, (" 0\n(0.0, 1.0] a\nNaN b\n(2.0, 3.0] c")), + ], + ) + def test_repr_missing(self, constructor, expected): + # GH 25984 + index = IntervalIndex.from_tuples([(0, 1), np.nan, (2, 3)]) + obj = constructor(list("abc"), index=index) + result = repr(obj) + assert result == expected + + @pytest.mark.parametrize( + "tuples, closed, expected_data", + [ + ([(0, 1), (1, 2), (2, 3)], "left", ["[0, 1)", "[1, 2)", "[2, 3)"]), + ( + [(0.5, 1.0), np.nan, (2.0, 3.0)], + "right", + ["(0.5, 1.0]", "NaN", "(2.0, 3.0]"], + ), + ( + [ + (Timestamp("20180101"), Timestamp("20180102")), + np.nan, + ((Timestamp("20180102"), Timestamp("20180103"))), + ], + "both", + ["[2018-01-01, 2018-01-02]", "NaN", "[2018-01-02, 2018-01-03]"], + ), + ( + [ + (Timedelta("0 days"), Timedelta("1 days")), + (Timedelta("1 days"), Timedelta("2 days")), + np.nan, + ], + "neither", + [ + "(0 days 00:00:00, 1 days 00:00:00)", + "(1 days 00:00:00, 2 days 00:00:00)", + "NaN", + ], + ), + ], + ) + def test_to_native_types(self, tuples, closed, expected_data): + # GH 28210 + index = IntervalIndex.from_tuples(tuples, closed=closed) + result = index.to_native_types() + expected = np.array(expected_data) + tm.assert_numpy_array_equal(result, expected) diff --git a/pandas/tests/indexes/interval/test_interval_new.py b/pandas/tests/indexes/interval/test_indexing.py similarity index 70% rename from pandas/tests/indexes/interval/test_interval_new.py rename to pandas/tests/indexes/interval/test_indexing.py index d92559d2e3e49..05d8aee2a8fb7 100644 --- a/pandas/tests/indexes/interval/test_interval_new.py +++ b/pandas/tests/indexes/interval/test_indexing.py @@ -3,12 +3,12 @@ import numpy as np import pytest -from pandas import Interval, IntervalIndex +from pandas import Interval, IntervalIndex, Timedelta, date_range, timedelta_range from pandas.core.indexes.base import InvalidIndexError import pandas.util.testing as tm -class TestIntervalIndex: +class TestGetLoc: @pytest.mark.parametrize("side", ["right", "left", "both", "neither"]) def test_get_loc_interval(self, closed, side): @@ -56,129 +56,111 @@ def test_get_loc_scalar(self, closed, scalar): with pytest.raises(KeyError, match=str(scalar)): idx.get_loc(scalar) - def test_slice_locs_with_interval(self): - - # increasing monotonically - index = IntervalIndex.from_tuples([(0, 2), (1, 3), (2, 4)]) - - assert index.slice_locs(start=Interval(0, 2), end=Interval(2, 4)) == (0, 3) - assert index.slice_locs(start=Interval(0, 2)) == (0, 3) - assert index.slice_locs(end=Interval(2, 4)) == (0, 3) - assert index.slice_locs(end=Interval(0, 2)) == (0, 1) - assert index.slice_locs(start=Interval(2, 4), end=Interval(0, 2)) == (2, 1) - - # decreasing monotonically - index = IntervalIndex.from_tuples([(2, 4), (1, 3), (0, 2)]) - - assert index.slice_locs(start=Interval(0, 2), end=Interval(2, 4)) == (2, 1) - assert index.slice_locs(start=Interval(0, 2)) == (2, 3) - assert index.slice_locs(end=Interval(2, 4)) == (0, 1) - assert index.slice_locs(end=Interval(0, 2)) == (0, 3) - assert index.slice_locs(start=Interval(2, 4), end=Interval(0, 2)) == (0, 3) - - # sorted duplicates - index = IntervalIndex.from_tuples([(0, 2), (0, 2), (2, 4)]) - - assert index.slice_locs(start=Interval(0, 2), end=Interval(2, 4)) == (0, 3) - assert index.slice_locs(start=Interval(0, 2)) == (0, 3) - assert index.slice_locs(end=Interval(2, 4)) == (0, 3) - assert index.slice_locs(end=Interval(0, 2)) == (0, 2) - assert index.slice_locs(start=Interval(2, 4), end=Interval(0, 2)) == (2, 2) - - # unsorted duplicates - index = IntervalIndex.from_tuples([(0, 2), (2, 4), (0, 2)]) + @pytest.mark.parametrize("scalar", [-1, 0, 0.5, 3, 4.5, 5, 6]) + def test_get_loc_length_one_scalar(self, scalar, closed): + # GH 20921 + index = IntervalIndex.from_tuples([(0, 5)], closed=closed) + if scalar in index[0]: + result = index.get_loc(scalar) + assert result == 0 + else: + with pytest.raises(KeyError, match=str(scalar)): + index.get_loc(scalar) + + @pytest.mark.parametrize("other_closed", ["left", "right", "both", "neither"]) + @pytest.mark.parametrize("left, right", [(0, 5), (-1, 4), (-1, 6), (6, 7)]) + def test_get_loc_length_one_interval(self, left, right, closed, other_closed): + # GH 20921 + index = IntervalIndex.from_tuples([(0, 5)], closed=closed) + interval = Interval(left, right, closed=other_closed) + if interval == index[0]: + result = index.get_loc(interval) + assert result == 0 + else: + with pytest.raises( + KeyError, + match=re.escape( + "Interval({left}, {right}, closed='{other_closed}')".format( + left=left, right=right, other_closed=other_closed + ) + ), + ): + index.get_loc(interval) + + # Make consistent with test_interval_new.py (see #16316, #16386) + @pytest.mark.parametrize( + "breaks", + [ + date_range("20180101", periods=4), + date_range("20180101", periods=4, tz="US/Eastern"), + timedelta_range("0 days", periods=4), + ], + ids=lambda x: str(x.dtype), + ) + def test_get_loc_datetimelike_nonoverlapping(self, breaks): + # GH 20636 + # nonoverlapping = IntervalIndex method and no i8 conversion + index = IntervalIndex.from_breaks(breaks) - with pytest.raises( - KeyError, - match=re.escape( - '"Cannot get left slice bound for non-unique label:' - " Interval(0, 2, closed='right')\"" - ), - ): - index.slice_locs(start=Interval(0, 2), end=Interval(2, 4)) + value = index[0].mid + result = index.get_loc(value) + expected = 0 + assert result == expected - with pytest.raises( - KeyError, - match=re.escape( - '"Cannot get left slice bound for non-unique label:' - " Interval(0, 2, closed='right')\"" - ), - ): - index.slice_locs(start=Interval(0, 2)) + interval = Interval(index[0].left, index[0].right) + result = index.get_loc(interval) + expected = 0 + assert result == expected - assert index.slice_locs(end=Interval(2, 4)) == (0, 2) - - with pytest.raises( - KeyError, - match=re.escape( - '"Cannot get right slice bound for non-unique label:' - " Interval(0, 2, closed='right')\"" + @pytest.mark.parametrize( + "arrays", + [ + (date_range("20180101", periods=4), date_range("20180103", periods=4)), + ( + date_range("20180101", periods=4, tz="US/Eastern"), + date_range("20180103", periods=4, tz="US/Eastern"), ), - ): - index.slice_locs(end=Interval(0, 2)) - - with pytest.raises( - KeyError, - match=re.escape( - '"Cannot get right slice bound for non-unique label:' - " Interval(0, 2, closed='right')\"" + ( + timedelta_range("0 days", periods=4), + timedelta_range("2 days", periods=4), ), - ): - index.slice_locs(start=Interval(2, 4), end=Interval(0, 2)) - - # another unsorted duplicates - index = IntervalIndex.from_tuples([(0, 2), (0, 2), (2, 4), (1, 3)]) - - assert index.slice_locs(start=Interval(0, 2), end=Interval(2, 4)) == (0, 3) - assert index.slice_locs(start=Interval(0, 2)) == (0, 4) - assert index.slice_locs(end=Interval(2, 4)) == (0, 3) - assert index.slice_locs(end=Interval(0, 2)) == (0, 2) - assert index.slice_locs(start=Interval(2, 4), end=Interval(0, 2)) == (2, 2) + ], + ids=lambda x: str(x[0].dtype), + ) + def test_get_loc_datetimelike_overlapping(self, arrays): + # GH 20636 + index = IntervalIndex.from_arrays(*arrays) - def test_slice_locs_with_ints_and_floats_succeeds(self): + value = index[0].mid + Timedelta("12 hours") + result = index.get_loc(value) + expected = slice(0, 2, None) + assert result == expected - # increasing non-overlapping - index = IntervalIndex.from_tuples([(0, 1), (1, 2), (3, 4)]) + interval = Interval(index[0].left, index[0].right) + result = index.get_loc(interval) + expected = 0 + assert result == expected - assert index.slice_locs(0, 1) == (0, 1) - assert index.slice_locs(0, 2) == (0, 2) - assert index.slice_locs(0, 3) == (0, 2) - assert index.slice_locs(3, 1) == (2, 1) - assert index.slice_locs(3, 4) == (2, 3) - assert index.slice_locs(0, 4) == (0, 3) - - # decreasing non-overlapping - index = IntervalIndex.from_tuples([(3, 4), (1, 2), (0, 1)]) - assert index.slice_locs(0, 1) == (3, 3) - assert index.slice_locs(0, 2) == (3, 2) - assert index.slice_locs(0, 3) == (3, 1) - assert index.slice_locs(3, 1) == (1, 3) - assert index.slice_locs(3, 4) == (1, 1) - assert index.slice_locs(0, 4) == (3, 1) - - @pytest.mark.parametrize("query", [[0, 1], [0, 2], [0, 3], [0, 4]]) @pytest.mark.parametrize( - "tuples", + "values", [ - [(0, 2), (1, 3), (2, 4)], - [(2, 4), (1, 3), (0, 2)], - [(0, 2), (0, 2), (2, 4)], - [(0, 2), (2, 4), (0, 2)], - [(0, 2), (0, 2), (2, 4), (1, 3)], + date_range("2018-01-04", periods=4, freq="-1D"), + date_range("2018-01-04", periods=4, freq="-1D", tz="US/Eastern"), + timedelta_range("3 days", periods=4, freq="-1D"), + np.arange(3.0, -1.0, -1.0), + np.arange(3, -1, -1), ], + ids=lambda x: str(x.dtype), ) - def test_slice_locs_with_ints_and_floats_errors(self, tuples, query): - start, stop = query - index = IntervalIndex.from_tuples(tuples) - with pytest.raises( - KeyError, - match=( - "'can only get slices from an IntervalIndex if bounds are" - " non-overlapping and all monotonic increasing or decreasing'" - ), - ): - index.slice_locs(start, stop) + def test_get_loc_decreasing(self, values): + # GH 25860 + index = IntervalIndex.from_arrays(values[1:], values[:-1]) + result = index.get_loc(index[0]) + expected = 0 + assert result == expected + +class TestGetIndexer: @pytest.mark.parametrize( "query, expected", [ @@ -233,6 +215,22 @@ def test_get_indexer_with_int_and_float(self, query, expected): expected = np.array(expected, dtype="intp") tm.assert_numpy_array_equal(result, expected) + @pytest.mark.parametrize("item", [[3], np.arange(0.5, 5, 0.5)]) + def test_get_indexer_length_one(self, item, closed): + # GH 17284 + index = IntervalIndex.from_tuples([(0, 5)], closed=closed) + result = index.get_indexer(item) + expected = np.array([0] * len(item), dtype="intp") + tm.assert_numpy_array_equal(result, expected) + + @pytest.mark.parametrize("size", [1, 5]) + def test_get_indexer_length_one_interval(self, size, closed): + # GH 17284 + index = IntervalIndex.from_tuples([(0, 5)], closed=closed) + result = index.get_indexer([Interval(0, 5, closed)] * size) + expected = np.array([0] * size, dtype="intp") + tm.assert_numpy_array_equal(result, expected) + @pytest.mark.parametrize( "tuples, closed", [ @@ -288,19 +286,127 @@ def test_get_indexer_non_unique_with_int_and_float(self, query, expected): # TODO we may also want to test get_indexer for the case when # the intervals are duplicated, decreasing, non-monotonic, etc.. - def test_contains_dunder(self): - index = IntervalIndex.from_arrays([0, 1], [1, 2], closed="right") +class TestSliceLocs: + def test_slice_locs_with_interval(self): + + # increasing monotonically + index = IntervalIndex.from_tuples([(0, 2), (1, 3), (2, 4)]) + + assert index.slice_locs(start=Interval(0, 2), end=Interval(2, 4)) == (0, 3) + assert index.slice_locs(start=Interval(0, 2)) == (0, 3) + assert index.slice_locs(end=Interval(2, 4)) == (0, 3) + assert index.slice_locs(end=Interval(0, 2)) == (0, 1) + assert index.slice_locs(start=Interval(2, 4), end=Interval(0, 2)) == (2, 1) + + # decreasing monotonically + index = IntervalIndex.from_tuples([(2, 4), (1, 3), (0, 2)]) + + assert index.slice_locs(start=Interval(0, 2), end=Interval(2, 4)) == (2, 1) + assert index.slice_locs(start=Interval(0, 2)) == (2, 3) + assert index.slice_locs(end=Interval(2, 4)) == (0, 1) + assert index.slice_locs(end=Interval(0, 2)) == (0, 3) + assert index.slice_locs(start=Interval(2, 4), end=Interval(0, 2)) == (0, 3) + + # sorted duplicates + index = IntervalIndex.from_tuples([(0, 2), (0, 2), (2, 4)]) + + assert index.slice_locs(start=Interval(0, 2), end=Interval(2, 4)) == (0, 3) + assert index.slice_locs(start=Interval(0, 2)) == (0, 3) + assert index.slice_locs(end=Interval(2, 4)) == (0, 3) + assert index.slice_locs(end=Interval(0, 2)) == (0, 2) + assert index.slice_locs(start=Interval(2, 4), end=Interval(0, 2)) == (2, 2) + + # unsorted duplicates + index = IntervalIndex.from_tuples([(0, 2), (2, 4), (0, 2)]) + + with pytest.raises( + KeyError, + match=re.escape( + '"Cannot get left slice bound for non-unique label:' + " Interval(0, 2, closed='right')\"" + ), + ): + index.slice_locs(start=Interval(0, 2), end=Interval(2, 4)) - # __contains__ requires perfect matches to intervals. - assert 0 not in index - assert 1 not in index - assert 2 not in index + with pytest.raises( + KeyError, + match=re.escape( + '"Cannot get left slice bound for non-unique label:' + " Interval(0, 2, closed='right')\"" + ), + ): + index.slice_locs(start=Interval(0, 2)) + + assert index.slice_locs(end=Interval(2, 4)) == (0, 2) + + with pytest.raises( + KeyError, + match=re.escape( + '"Cannot get right slice bound for non-unique label:' + " Interval(0, 2, closed='right')\"" + ), + ): + index.slice_locs(end=Interval(0, 2)) - assert Interval(0, 1, closed="right") in index - assert Interval(0, 2, closed="right") not in index - assert Interval(0, 0.5, closed="right") not in index - assert Interval(3, 5, closed="right") not in index - assert Interval(-1, 0, closed="left") not in index - assert Interval(0, 1, closed="left") not in index - assert Interval(0, 1, closed="both") not in index + with pytest.raises( + KeyError, + match=re.escape( + '"Cannot get right slice bound for non-unique label:' + " Interval(0, 2, closed='right')\"" + ), + ): + index.slice_locs(start=Interval(2, 4), end=Interval(0, 2)) + + # another unsorted duplicates + index = IntervalIndex.from_tuples([(0, 2), (0, 2), (2, 4), (1, 3)]) + + assert index.slice_locs(start=Interval(0, 2), end=Interval(2, 4)) == (0, 3) + assert index.slice_locs(start=Interval(0, 2)) == (0, 4) + assert index.slice_locs(end=Interval(2, 4)) == (0, 3) + assert index.slice_locs(end=Interval(0, 2)) == (0, 2) + assert index.slice_locs(start=Interval(2, 4), end=Interval(0, 2)) == (2, 2) + + def test_slice_locs_with_ints_and_floats_succeeds(self): + + # increasing non-overlapping + index = IntervalIndex.from_tuples([(0, 1), (1, 2), (3, 4)]) + + assert index.slice_locs(0, 1) == (0, 1) + assert index.slice_locs(0, 2) == (0, 2) + assert index.slice_locs(0, 3) == (0, 2) + assert index.slice_locs(3, 1) == (2, 1) + assert index.slice_locs(3, 4) == (2, 3) + assert index.slice_locs(0, 4) == (0, 3) + + # decreasing non-overlapping + index = IntervalIndex.from_tuples([(3, 4), (1, 2), (0, 1)]) + assert index.slice_locs(0, 1) == (3, 3) + assert index.slice_locs(0, 2) == (3, 2) + assert index.slice_locs(0, 3) == (3, 1) + assert index.slice_locs(3, 1) == (1, 3) + assert index.slice_locs(3, 4) == (1, 1) + assert index.slice_locs(0, 4) == (3, 1) + + @pytest.mark.parametrize("query", [[0, 1], [0, 2], [0, 3], [0, 4]]) + @pytest.mark.parametrize( + "tuples", + [ + [(0, 2), (1, 3), (2, 4)], + [(2, 4), (1, 3), (0, 2)], + [(0, 2), (0, 2), (2, 4)], + [(0, 2), (2, 4), (0, 2)], + [(0, 2), (0, 2), (2, 4), (1, 3)], + ], + ) + def test_slice_locs_with_ints_and_floats_errors(self, tuples, query): + start, stop = query + index = IntervalIndex.from_tuples(tuples) + with pytest.raises( + KeyError, + match=( + "'can only get slices from an IntervalIndex if bounds are" + " non-overlapping and all monotonic increasing or decreasing'" + ), + ): + index.slice_locs(start, stop) diff --git a/pandas/tests/indexes/interval/test_interval.py b/pandas/tests/indexes/interval/test_interval.py index eeb0f43f4b900..73eacd8c4856e 100644 --- a/pandas/tests/indexes/interval/test_interval.py +++ b/pandas/tests/indexes/interval/test_interval.py @@ -18,7 +18,6 @@ timedelta_range, ) import pandas.core.common as com -from pandas.tests.indexes.common import Base import pandas.util.testing as tm @@ -27,13 +26,8 @@ def name(request): return request.param -class TestIntervalIndex(Base): - _holder = IntervalIndex - - def setup_method(self, method): - self.index = IntervalIndex.from_arrays([0, 1], [1, 2]) - self.index_with_nan = IntervalIndex.from_tuples([(0, 1), np.nan, (1, 2)]) - self.indices = dict(intervalIndex=tm.makeIntervalIndex(10)) +class TestIntervalIndex: + index = IntervalIndex.from_arrays([0, 1], [1, 2]) def create_index(self, closed="right"): return IntervalIndex.from_breaks(range(11), closed=closed) @@ -161,47 +155,6 @@ def test_ensure_copied_data(self, closed): index.right.values, result.right.values, check_same="copy" ) - def test_equals(self, closed): - expected = IntervalIndex.from_breaks(np.arange(5), closed=closed) - assert expected.equals(expected) - assert expected.equals(expected.copy()) - - assert not expected.equals(expected.astype(object)) - assert not expected.equals(np.array(expected)) - assert not expected.equals(list(expected)) - - assert not expected.equals([1, 2]) - assert not expected.equals(np.array([1, 2])) - assert not expected.equals(pd.date_range("20130101", periods=2)) - - expected_name1 = IntervalIndex.from_breaks( - np.arange(5), closed=closed, name="foo" - ) - expected_name2 = IntervalIndex.from_breaks( - np.arange(5), closed=closed, name="bar" - ) - assert expected.equals(expected_name1) - assert expected_name1.equals(expected_name2) - - for other_closed in {"left", "right", "both", "neither"} - {closed}: - expected_other_closed = IntervalIndex.from_breaks( - np.arange(5), closed=other_closed - ) - assert not expected.equals(expected_other_closed) - - @pytest.mark.parametrize("klass", [list, tuple, np.array, pd.Series]) - def test_where(self, closed, klass): - idx = self.create_index(closed=closed) - cond = [True] * len(idx) - expected = idx - result = expected.where(klass(cond)) - tm.assert_index_equal(result, expected) - - cond = [False] + [True] * len(idx[1:]) - expected = IntervalIndex([np.nan] + idx[1:].tolist()) - result = idx.where(klass(cond)) - tm.assert_index_equal(result, expected) - def test_delete(self, closed): expected = IntervalIndex.from_breaks(np.arange(1, 11), closed=closed) result = self.create_index(closed=closed).delete(0) @@ -254,16 +207,6 @@ def test_insert(self, data): result = data.insert(1, na) tm.assert_index_equal(result, expected) - def test_take(self, closed): - index = self.create_index(closed=closed) - - result = index.take(range(10)) - tm.assert_index_equal(result, index) - - result = index.take([0, 0, 1]) - expected = IntervalIndex.from_arrays([0, 0, 1], [1, 1, 2], closed=closed) - tm.assert_index_equal(result, expected) - def test_is_unique_interval(self, closed): """ Interval specific tests for is_unique in addition to base class tests @@ -351,112 +294,6 @@ def test_monotonic(self, closed): assert idx.is_monotonic_decreasing is True assert idx._is_strictly_monotonic_decreasing is True - @pytest.mark.skip(reason="not a valid repr as we use interval notation") - def test_repr(self): - i = IntervalIndex.from_tuples([(0, 1), (1, 2)], closed="right") - expected = ( - "IntervalIndex(left=[0, 1]," - "\n right=[1, 2]," - "\n closed='right'," - "\n dtype='interval[int64]')" - ) - assert repr(i) == expected - - i = IntervalIndex.from_tuples( - (Timestamp("20130101"), Timestamp("20130102")), - (Timestamp("20130102"), Timestamp("20130103")), - closed="right", - ) - expected = ( - "IntervalIndex(left=['2013-01-01', '2013-01-02']," - "\n right=['2013-01-02', '2013-01-03']," - "\n closed='right'," - "\n dtype='interval[datetime64[ns]]')" - ) - assert repr(i) == expected - - @pytest.mark.skip(reason="not a valid repr as we use interval notation") - def test_repr_max_seq_item_setting(self): - super().test_repr_max_seq_item_setting() - - @pytest.mark.skip(reason="not a valid repr as we use interval notation") - def test_repr_roundtrip(self): - super().test_repr_roundtrip() - - def test_frame_repr(self): - # https://github.com/pandas-dev/pandas/pull/24134/files - df = pd.DataFrame( - {"A": [1, 2, 3, 4]}, index=pd.IntervalIndex.from_breaks([0, 1, 2, 3, 4]) - ) - result = repr(df) - expected = " A\n(0, 1] 1\n(1, 2] 2\n(2, 3] 3\n(3, 4] 4" - assert result == expected - - @pytest.mark.parametrize( - "constructor,expected", - [ - ( - pd.Series, - ( - "(0.0, 1.0] a\n" - "NaN b\n" - "(2.0, 3.0] c\n" - "dtype: object" - ), - ), - ( - pd.DataFrame, - (" 0\n(0.0, 1.0] a\nNaN b\n(2.0, 3.0] c"), - ), - ], - ) - def test_repr_missing(self, constructor, expected): - # GH 25984 - index = IntervalIndex.from_tuples([(0, 1), np.nan, (2, 3)]) - obj = constructor(list("abc"), index=index) - result = repr(obj) - assert result == expected - - @pytest.mark.parametrize( - "tuples, closed, expected_data", - [ - ([(0, 1), (1, 2), (2, 3)], "left", ["[0, 1)", "[1, 2)", "[2, 3)"]), - ( - [(0.5, 1.0), np.nan, (2.0, 3.0)], - "right", - ["(0.5, 1.0]", "NaN", "(2.0, 3.0]"], - ), - ( - [ - (Timestamp("20180101"), Timestamp("20180102")), - np.nan, - ((Timestamp("20180102"), Timestamp("20180103"))), - ], - "both", - ["[2018-01-01, 2018-01-02]", "NaN", "[2018-01-02, 2018-01-03]"], - ), - ( - [ - (Timedelta("0 days"), Timedelta("1 days")), - (Timedelta("1 days"), Timedelta("2 days")), - np.nan, - ], - "neither", - [ - "(0 days 00:00:00, 1 days 00:00:00)", - "(1 days 00:00:00, 2 days 00:00:00)", - "NaN", - ], - ), - ], - ) - def test_to_native_types(self, tuples, closed, expected_data): - # GH 28210 - index = IntervalIndex.from_tuples(tuples, closed=closed) - result = index.to_native_types() - expected = np.array(expected_data) - tm.assert_numpy_array_equal(result, expected) - def test_get_item(self, closed): i = IntervalIndex.from_arrays((0, 1, np.nan), (1, 2, np.nan), closed=closed) assert i[0] == Interval(0.0, 1.0, closed=closed) @@ -477,125 +314,6 @@ def test_get_item(self, closed): ) tm.assert_index_equal(result, expected) - @pytest.mark.parametrize("scalar", [-1, 0, 0.5, 3, 4.5, 5, 6]) - def test_get_loc_length_one_scalar(self, scalar, closed): - # GH 20921 - index = IntervalIndex.from_tuples([(0, 5)], closed=closed) - if scalar in index[0]: - result = index.get_loc(scalar) - assert result == 0 - else: - with pytest.raises(KeyError, match=str(scalar)): - index.get_loc(scalar) - - @pytest.mark.parametrize("other_closed", ["left", "right", "both", "neither"]) - @pytest.mark.parametrize("left, right", [(0, 5), (-1, 4), (-1, 6), (6, 7)]) - def test_get_loc_length_one_interval(self, left, right, closed, other_closed): - # GH 20921 - index = IntervalIndex.from_tuples([(0, 5)], closed=closed) - interval = Interval(left, right, closed=other_closed) - if interval == index[0]: - result = index.get_loc(interval) - assert result == 0 - else: - with pytest.raises( - KeyError, - match=re.escape( - "Interval({left}, {right}, closed='{other_closed}')".format( - left=left, right=right, other_closed=other_closed - ) - ), - ): - index.get_loc(interval) - - # Make consistent with test_interval_new.py (see #16316, #16386) - @pytest.mark.parametrize( - "breaks", - [ - date_range("20180101", periods=4), - date_range("20180101", periods=4, tz="US/Eastern"), - timedelta_range("0 days", periods=4), - ], - ids=lambda x: str(x.dtype), - ) - def test_get_loc_datetimelike_nonoverlapping(self, breaks): - # GH 20636 - # nonoverlapping = IntervalIndex method and no i8 conversion - index = IntervalIndex.from_breaks(breaks) - - value = index[0].mid - result = index.get_loc(value) - expected = 0 - assert result == expected - - interval = Interval(index[0].left, index[0].right) - result = index.get_loc(interval) - expected = 0 - assert result == expected - - @pytest.mark.parametrize( - "arrays", - [ - (date_range("20180101", periods=4), date_range("20180103", periods=4)), - ( - date_range("20180101", periods=4, tz="US/Eastern"), - date_range("20180103", periods=4, tz="US/Eastern"), - ), - ( - timedelta_range("0 days", periods=4), - timedelta_range("2 days", periods=4), - ), - ], - ids=lambda x: str(x[0].dtype), - ) - def test_get_loc_datetimelike_overlapping(self, arrays): - # GH 20636 - index = IntervalIndex.from_arrays(*arrays) - - value = index[0].mid + Timedelta("12 hours") - result = index.get_loc(value) - expected = slice(0, 2, None) - assert result == expected - - interval = Interval(index[0].left, index[0].right) - result = index.get_loc(interval) - expected = 0 - assert result == expected - - @pytest.mark.parametrize( - "values", - [ - date_range("2018-01-04", periods=4, freq="-1D"), - date_range("2018-01-04", periods=4, freq="-1D", tz="US/Eastern"), - timedelta_range("3 days", periods=4, freq="-1D"), - np.arange(3.0, -1.0, -1.0), - np.arange(3, -1, -1), - ], - ids=lambda x: str(x.dtype), - ) - def test_get_loc_decreasing(self, values): - # GH 25860 - index = IntervalIndex.from_arrays(values[1:], values[:-1]) - result = index.get_loc(index[0]) - expected = 0 - assert result == expected - - @pytest.mark.parametrize("item", [[3], np.arange(0.5, 5, 0.5)]) - def test_get_indexer_length_one(self, item, closed): - # GH 17284 - index = IntervalIndex.from_tuples([(0, 5)], closed=closed) - result = index.get_indexer(item) - expected = np.array([0] * len(item), dtype="intp") - tm.assert_numpy_array_equal(result, expected) - - @pytest.mark.parametrize("size", [1, 5]) - def test_get_indexer_length_one_interval(self, size, closed): - # GH 17284 - index = IntervalIndex.from_tuples([(0, 5)], closed=closed) - result = index.get_indexer([Interval(0, 5, closed)] * size) - expected = np.array([0] * size, dtype="intp") - tm.assert_numpy_array_equal(result, expected) - @pytest.mark.parametrize( "breaks", [ @@ -737,6 +455,23 @@ def test_contains_method(self): ): i.contains(Interval(0, 1)) + def test_contains_dunder(self): + + index = IntervalIndex.from_arrays([0, 1], [1, 2], closed="right") + + # __contains__ requires perfect matches to intervals. + assert 0 not in index + assert 1 not in index + assert 2 not in index + + assert Interval(0, 1, closed="right") in index + assert Interval(0, 2, closed="right") not in index + assert Interval(0, 0.5, closed="right") not in index + assert Interval(3, 5, closed="right") not in index + assert Interval(-1, 0, closed="left") not in index + assert Interval(0, 1, closed="left") not in index + assert Interval(0, 1, closed="both") not in index + def test_dropna(self, closed): expected = IntervalIndex.from_tuples([(0.0, 1.0), (1.0, 2.0)], closed=closed)