diff --git a/pandas/tests/indexes/interval/test_interval_new.py b/pandas/tests/indexes/interval/test_interval_new.py index c8b30e19daa02..71c7265b89a1d 100644 --- a/pandas/tests/indexes/interval/test_interval_new.py +++ b/pandas/tests/indexes/interval/test_interval_new.py @@ -13,13 +13,6 @@ class TestIntervalIndex(Base): - def _compare_tuple_of_numpy_array(self, result, expected): - lidx, ridx = result - lidx_expected, ridx_expected = expected - - tm.assert_numpy_array_equal(lidx, lidx_expected) - tm.assert_numpy_array_equal(ridx, ridx_expected) - @pytest.mark.parametrize("idx_side", ['right', 'left', 'both', 'neither']) @pytest.mark.parametrize("side", ['right', 'left', 'both', 'neither']) def test_get_loc_interval(self, idx_side, side): diff --git a/pandas/tests/indexes/interval/test_interval_overlaps_covers.py b/pandas/tests/indexes/interval/test_interval_overlaps_covers.py new file mode 100644 index 0000000000000..ef03e9be78abc --- /dev/null +++ b/pandas/tests/indexes/interval/test_interval_overlaps_covers.py @@ -0,0 +1,63 @@ +from __future__ import division + +import pytest +import numpy as np + +from pandas import IntervalIndex +from pandas.tests.indexes.common import Base +import pandas.util.testing as tm + +pytestmark = pytest.mark.skip(reason="new indexing tests for issue 16316") + + +class TestIntervalIndex(Base): + + def _compare_tuple_of_numpy_array(self, result, expected): + lidx, ridx = result + lidx_expected, ridx_expected = expected + + tm.assert_numpy_array_equal(lidx, lidx_expected) + tm.assert_numpy_array_equal(ridx, ridx_expected) + + @pytest.mark.parametrize("oth_side", ['right', 'left', 'both']) + def test_intervalIndex_covers_intervalIndex(self, idx): + + # class IntervalIndex: + # def covers(self, other: IntervalIndex) -> Tuple[IntegerArray1D, + # IntegerArray1D] + + idx = IntervalIndex.from_tuples([(0, 1), (2, 3), (1, 3)], + closed="right") + other = IntervalIndex.from_tuples([(0, 1), (2, 3), (1, 3)], + closed=oth_side) + + result = idx.covers(idx) + expected = { + "right": (np.array([0, 1, 2, 2]), np.array([0, 1, 1, 2])), + "left": (np.array([2]), np.array([1])), + "both": (np.array([0, 1, 2, 2]), np.array([0, 1, 1, 2])) + } + + self._compare_tuple_of_numpy_array(result, expected[oth_side]) + + @pytest.mark.parametrize("oth_side", ['right', 'left', 'both']) + def test_intervalIndex_overlaps_intervalIndex(self): + + # class IntervalIndex: + # def overlaps(self, other: IntervalIndex) -> Tuple[IntegerArray1D, + # IntegerArray1D] + + idx = IntervalIndex.from_tuples([(0, 1), (2, 3), (1, 3)], + closed="right") + other = IntervalIndex.from_tuples([(0, 1), (2, 3), (1, 3)], + closed=oth_side) + + result = idx.overlaps(idx) + expected = { + "right": (np.array([0, 1, 2, 2]), np.array([0, 1, 1, 2])), + "left": (np.array([0, 0, 1, 1, 2, 2]), + np.array([0, 2, 1, 2, 1, 2])), + "both": (np.array([0, 0, 1, 1, 2, 2]), + np.array([0, 2, 1, 2, 1, 2])) + } + self._compare_tuple_of_numpy_array(result, expected[oth_side]) diff --git a/pandas/tests/scalar/test_interval_new.py b/pandas/tests/scalar/test_interval_new.py new file mode 100644 index 0000000000000..55180e246c40e --- /dev/null +++ b/pandas/tests/scalar/test_interval_new.py @@ -0,0 +1,251 @@ +from __future__ import division + +import pytest +import numpy as np + +from pandas import Interval, IntervalIndex +from pandas.tests.indexes.common import Base +import pandas.util.testing as tm + +pytestmark = pytest.mark.skip(reason="new indexing tests for issue 16316") + + +class TestIntervalIndex(Base): + + @pytest.mark.parametrize("ivl_side", ['right', 'left', 'both', 'neither']) + @pytest.mark.parametrize("oth_side", ['right', 'left', 'both', 'neither']) + def test_interval_covers_interval(self, ivl_side, oth_side): + + # class Interval: + # def covers(self, other: Interval) -> bool + + assert Interval(1, 3).covers(Interval(1.5, 2.5)) + assert Interval(1, 3).covers(Interval(1, 2)) + assert Interval(1, 3).covers(Interval(2, 3)) + assert not Interval(1, 3).covers(Interval(0.5, 2.5)) + assert not Interval(1, 3).covers(Interval(1.5, 3.5)) + + ivl = Interval(1, 3, closed=ivl_side) + other = Interval(1, 3, closed=oth_side) + + should_cover = { + 'right': { + 'right': True, 'left': False, 'both': False, 'neither': True}, + 'left': { + 'right': False, 'left': True, 'both': False, 'neither': True}, + 'both': { + 'right': True, 'left': True, 'both': True, 'neither': True}, + 'neither': { + 'right': False, 'left': False, 'both': False, 'neither': True} + } + + result = ivl.covers(other) + expected = should_cover[ivl_side][oth_side] + assert result == expected + + @pytest.mark.parametrize("ivl_side", ['right', 'left', 'both', 'neither']) + @pytest.mark.parametrize("oth_side", ['right', 'left', 'both', 'neither']) + @pytest.mark.parametrize("ivl_range", [(1, 3), (-1, 1), (3, 5)]) + def test_interval_overlaps_interval(self, ivl_side, oth_side, ivl_range): + + # class Interval: + # def overlaps(self, other: Interval) -> bool + + assert Interval(1, 3).overlaps(Interval(1.5, 2.5)) + assert Interval(1, 3).overlaps(Interval(1, 2)) + assert Interval(1, 3).overlaps(Interval(2, 3)) + assert Interval(1, 3).overlaps(Interval(0.5, 2.5)) + assert Interval(1, 3).overlaps(Interval(1.5, 3.5)) + + assert not Interval(1, 3).overlaps(Interval(-1, 1)) + assert not Interval(1, 3).overlaps(Interval(3, 5)) + + ivl = Interval(*ivl_range, closed=ivl_side) + other = Interval(1, 3, closed=oth_side) + + should_overlap = { + # idx_side: + # ivl_side: {ivl_range: expected_result} + 'right': { + 'right': {(-1, 1): False, (1, 3): True, (3, 5): False}, + 'left': {(-1, 1): False, (1, 3): True, (3, 5): True}, + 'both': {(-1, 1): False, (1, 3): True, (3, 5): True}, + 'neither': {(-1, 1): False, (1, 3): True, (3, 5): False}, + }, + 'left': { + 'right': {(-1, 1): True, (1, 3): True, (3, 5): False}, + 'left': {(-1, 1): False, (1, 3): True, (3, 5): False}, + 'both': {(-1, 1): True, (1, 3): True, (3, 5): False}, + 'neither': {(-1, 1): False, (1, 3): True, (3, 5): False}, + }, + 'both': { + 'right': {(-1, 1): True, (1, 3): True, (3, 5): False}, + 'left': {(-1, 1): False, (1, 3): True, (3, 5): True}, + 'both': {(-1, 1): True, (1, 3): True, (3, 5): True}, + 'neither': {(-1, 1): False, (1, 3): True, (3, 5): False}, + }, + 'neither': { + 'right': {(-1, 1): False, (1, 3): True, (3, 5): False}, + 'left': {(-1, 1): False, (1, 3): True, (3, 5): False}, + 'both': {(-1, 1): False, (1, 3): True, (3, 5): False}, + 'neither': {(-1, 1): False, (1, 3): True, (3, 5): False}, + } + } + + result = ivl.overlaps(other) + expected = should_overlap[oth_side][ivl_side][ivl_range] + other_result = other.overlaps(ivl) + + assert result == expected == other_result + + @pytest.mark.parametrize("idx_side", ['right', 'left', 'both', 'neither']) + @pytest.mark.parametrize("ivl_side", ['right', 'left', 'both', 'neither']) + @pytest.mark.parametrize("ivl_range", [(1, 3), (0, 3), (0, 2), (2, 4)]) + def test_interval_covers_intervalIndex(self, idx_side, ivl_side, + ivl_range): + + # class Interval: + # def covers(self, other: IntervalIndex) -> IntegerArray1D + + # class IntervalIndex: + # def covers(self, other: Interval) -> IntegerArray1D + + idx = IntervalIndex.from_tuples([(0, 1), (2, 3), (1, 3)], + closed=idx_side) + ivl = Interval(*ivl_range, closed=ivl_side) + + should_cover = { + # idx_side: + # ivl_side: {ivl_range: expected_result} + 'right': { + 'right': { + (1, 3): [1, 2], (0, 3): [0, 1, 2], (0, 2): [0], + (2, 4): [1]}, + 'left': { + (1, 3): [], (0, 3): [0], (0, 2): [0], (2, 4): [1]}, + 'both': { + (1, 3): [1, 2], (0, 3): [0, 1, 2], (0, 2): [0], + (2, 4): [1]}, + 'neither': { + (1, 3): [], (0, 3): [0], (0, 2): [0], (2, 4): [1]} + }, + 'left': { + 'right': { + (1, 3): [1], (0, 3): [1, 2], (0, 2): [], (2, 4): []}, + 'left': { + (1, 3): [1, 2], (0, 3): [0, 1, 2], (0, 2): [0], + (2, 4): [1]}, + 'both': { + (1, 3): [1, 2], (0, 3): [0, 1, 2], (0, 2): [0], + (2, 4): [1]}, + 'neither': { + (1, 3): [1], (0, 3): [1, 2], (0, 2): [], (2, 4): []} + }, + 'both': { + 'right': { + (1, 3): [1], (0, 3): [1, 2], (0, 2): [], (2, 4): []}, + 'left': { + (1, 3): [], (0, 3): [0], (0, 2): [0], (2, 4): [1]}, + 'both': { + (1, 3): [1, 2], (0, 3): [0, 1, 2], (0, 2): [0], + (2, 4): [1]}, + 'neither': { + (1, 3): [], (0, 3): [], (0, 2): [], (2, 4): []} + }, + 'neither': { + 'right': { + (1, 3): [1, 2], (0, 3): [0, 1, 2], (0, 2): [0], + (2, 4): [1]}, + 'left': { + (1, 3): [1, 2], (0, 3): [0, 1, 2], (0, 2): [0], + (2, 4): [1]}, + 'both': { + (1, 3): [1, 2], (0, 3): [0, 1, 2], (0, 2): [0], + (2, 4): [1]}, + 'neither': { + (1, 3): [1, 2], (0, 3): [0, 1, 2], (0, 2): [0], + (2, 4): [1]} + } + } + + result = ivl.covers(idx) + expected = np.array(should_cover[idx_side][ivl_side][ivl_range]) + other_result = idx.covers(ivl) + + tm.assert_numpy_array_equal(result, expected) + tm.assert_numpy_array_equal(other_result, expected) + + @pytest.mark.parametrize("idx_side", ['right', 'left', 'both', 'neither']) + @pytest.mark.parametrize("ivl_side", ['right', 'left', 'both', 'neither']) + @pytest.mark.parametrize("ivl_range", [(1, 3), (1, 2), (0, 2), (3, 4)]) + def test_interval_overlaps_intervalIndex(self, idx_side, ivl_side, + ivl_range): + + # class Interval: + # def overlaps(self, other: IntervalIndex) -> IntegerArray1D + + # class IntervalIndex: + # def overlaps(self, other: Interval) -> IntegerArray1D + + idx = IntervalIndex.from_tuples([(0, 1), (2, 3), (1, 3)], + closed=idx_side) + ivl = Interval(*ivl_range, closed=ivl_side) + + should_overlap = { + # idx_side: + # ivl_side: {ivl_range: expected_result} + 'right': { + 'right': { + (1, 3): [1, 2], (1, 2): [2], (0, 2): [0, 2], (3, 4): []}, + 'left': { + (1, 3): [0, 1, 2], (1, 2): [0, 2], (0, 2): [0, 2], + (3, 4): [1, 2]}, + 'both': { + (1, 3): [0, 1, 2], (1, 2): [0, 2], (0, 2): [0, 2], + (3, 4): [1, 2]}, + 'neither': { + (1, 3): [1, 2], (1, 2): [2], (0, 2): [0, 2], (3, 4): []}, + }, + 'left': { + 'right': { + (1, 3): [1, 2], (1, 2): [1, 2], (0, 2): [0, 1, 2], + (3, 4): []}, + 'left': { + (1, 3): [1, 2], (1, 2): [2], (0, 2): [0, 2], (3, 4): []}, + 'both': { + (1, 3): [1, 2], (1, 2): [1, 2], (0, 2): [0, 1, 2], + (3, 4): []}, + 'neither': { + (1, 3): [1, 2], (1, 2): [2], (0, 2): [0, 2], (3, 4): []}, + }, + 'both': { + 'right': { + (1, 3): [1, 2], (1, 2): [1, 2], (0, 2): [0, 1, 2], + (3, 4): []}, + 'left': { + (1, 3): [0, 1, 2], (1, 2): [0, 2], (0, 2): [0, 2], + (3, 4): [1, 2]}, + 'both': { + (1, 3): [0, 1, 2], (1, 2): [0, 1, 2], (0, 2): [0, 1, 2], + (3, 4): [1, 2]}, + 'neither': { + (1, 3): [1, 2], (1, 2): [2], (0, 2): [0, 2], (3, 4): []}, + }, + 'neither': { + 'right': { + (1, 3): [1, 2], (1, 2): [2], (0, 2): [0, 2], (3, 4): []}, + 'left': { + (1, 3): [1, 2], (1, 2): [2], (0, 2): [0, 2], (3, 4): []}, + 'both': { + (1, 3): [1, 2], (1, 2): [2], (0, 2): [0, 2], (3, 4): []}, + 'neither': { + (1, 3): [1, 2], (1, 2): [2], (0, 2): [0, 2], (3, 4): []}, + } + } + + result = ivl.overlaps(idx) + expected = np.array(should_overlap[idx_side][ivl_side][ivl_range]) + other_result = idx.overlaps(ivl) + + tm.assert_numpy_array_equal(result, expected) + tm.assert_numpy_array_equal(other_result, expected)