|
| 1 | +"""Tests for Interval-Interval operations, such as overlaps, contains, etc.""" |
| 2 | +import numpy as np |
| 3 | +import pytest |
| 4 | + |
| 5 | +import pandas.util.testing as tm |
| 6 | +from pandas import Interval, IntervalIndex, Timedelta, Timestamp |
| 7 | +from pandas.core.arrays import IntervalArray |
| 8 | + |
| 9 | + |
| 10 | +@pytest.fixture(params=[IntervalArray, IntervalIndex]) |
| 11 | +def constructor(request): |
| 12 | + """ |
| 13 | + Fixture for testing both interval container classes. |
| 14 | + """ |
| 15 | + return request.param |
| 16 | + |
| 17 | + |
| 18 | +@pytest.fixture(params=[ |
| 19 | + (Timedelta('0 days'), Timedelta('1 day')), |
| 20 | + (Timestamp('2018-01-01'), Timedelta('1 day')), |
| 21 | + (0, 1)], ids=lambda x: type(x[0]).__name__) |
| 22 | +def start_shift(request): |
| 23 | + """ |
| 24 | + Fixture for generating intervals of different types from a start value |
| 25 | + and a shift value that can be added to start to generate an endpoint. |
| 26 | + """ |
| 27 | + return request.param |
| 28 | + |
| 29 | + |
| 30 | +class TestOverlaps(object): |
| 31 | + |
| 32 | + def test_overlaps_interval( |
| 33 | + self, constructor, start_shift, closed, other_closed): |
| 34 | + start, shift = start_shift |
| 35 | + interval = Interval(start, start + 3 * shift, other_closed) |
| 36 | + |
| 37 | + # intervals: identical, nested, spanning, partial, adjacent, disjoint |
| 38 | + tuples = [(start, start + 3 * shift), |
| 39 | + (start + shift, start + 2 * shift), |
| 40 | + (start - shift, start + 4 * shift), |
| 41 | + (start + 2 * shift, start + 4 * shift), |
| 42 | + (start + 3 * shift, start + 4 * shift), |
| 43 | + (start + 4 * shift, start + 5 * shift)] |
| 44 | + interval_container = constructor.from_tuples(tuples, closed) |
| 45 | + |
| 46 | + adjacent = (interval.closed_right and interval_container.closed_left) |
| 47 | + expected = np.array([True, True, True, True, adjacent, False]) |
| 48 | + result = interval_container.overlaps(interval) |
| 49 | + tm.assert_numpy_array_equal(result, expected) |
| 50 | + |
| 51 | + @pytest.mark.parametrize('other_constructor', [ |
| 52 | + IntervalArray, IntervalIndex]) |
| 53 | + def test_overlaps_interval_container(self, constructor, other_constructor): |
| 54 | + # TODO: modify this test when implemented |
| 55 | + interval_container = constructor.from_breaks(range(5)) |
| 56 | + other_container = other_constructor.from_breaks(range(5)) |
| 57 | + with pytest.raises(NotImplementedError): |
| 58 | + interval_container.overlaps(other_container) |
| 59 | + |
| 60 | + def test_overlaps_na(self, constructor, start_shift): |
| 61 | + """NA values are marked as False""" |
| 62 | + start, shift = start_shift |
| 63 | + interval = Interval(start, start + shift) |
| 64 | + |
| 65 | + tuples = [(start, start + shift), |
| 66 | + np.nan, |
| 67 | + (start + 2 * shift, start + 3 * shift)] |
| 68 | + interval_container = constructor.from_tuples(tuples) |
| 69 | + |
| 70 | + expected = np.array([True, False, False]) |
| 71 | + result = interval_container.overlaps(interval) |
| 72 | + tm.assert_numpy_array_equal(result, expected) |
| 73 | + |
| 74 | + @pytest.mark.parametrize('other', [ |
| 75 | + 10, True, 'foo', Timedelta('1 day'), Timestamp('2018-01-01')], |
| 76 | + ids=lambda x: type(x).__name__) |
| 77 | + def test_overlaps_invalid_type(self, constructor, other): |
| 78 | + interval_container = constructor.from_breaks(range(5)) |
| 79 | + msg = '`other` must be Interval-like, got {other}'.format( |
| 80 | + other=type(other).__name__) |
| 81 | + with tm.assert_raises_regex(TypeError, msg): |
| 82 | + interval_container.overlaps(other) |
0 commit comments