Skip to content

Commit

Permalink
allowing coverage method to accept interval array as domain specifica…
Browse files Browse the repository at this point in the history
…tion (#16)
  • Loading branch information
venaturum committed Oct 16, 2021
1 parent b47ee7d commit 37a76c0
Show file tree
Hide file tree
Showing 4 changed files with 42 additions and 11 deletions.
16 changes: 12 additions & 4 deletions piso/docstrings/accessor.py
Original file line number Diff line number Diff line change
Expand Up @@ -593,10 +593,12 @@ def join_params(list_of_param_strings):
Parameters
----------
domain : :class:`pandas.Interval`, or tuple equivalent, optional
Specifies the domain (lower and upper bounds) over which to assess the "coverage".
If *domain* is `None`, then the domain is considered to be the extremities of the intervals
contained in *interval_array*
domain : :py:class:`tuple`, :class:`pandas.Interval`, :class:`pandas.IntervalIndex` or :class:`pandas.arrays.IntervalArray`, optional
Specifies the domain over which to calculate the "coverage". If *domain* is `None`,
then the domain is considered to be the extremities of the intervals contained in the interval array the accessor belongs to.
If *domain* is a tuple then it should specify lower and upper bounds, and be equivalent to a
:class:`pandas.Interval`. If *domain* is a :class:`pandas.IntervalIndex` or :class:`pandas.arrays.IntervalArray`
then the intervals it contains define a possibly disconnected domain.
Returns
----------
Expand All @@ -622,6 +624,12 @@ def join_params(list_of_param_strings):
>>> arr1.piso.coverage(pd.Interval(-10, 10))
0.3
>>> domain = pd.arrays.IntervalArray.from_tuples(
... [(4,6), (7, 9)],
... )
>>> arr1.piso.coverage(domain)
0.5
"""

complement_docstring = """
Expand Down
16 changes: 12 additions & 4 deletions piso/docstrings/intervalarray.py
Original file line number Diff line number Diff line change
Expand Up @@ -599,10 +599,12 @@ def join_params(list_of_param_strings):
----------
interval_array : :class:`pandas.IntervalIndex` or :class:`pandas.arrays.IntervalArray`
Contains the (possibly overlapping) intervals which partially, or wholly cover the domain.
domain : :class:`pandas.Interval`, or tuple equivalent, optional
Specifies the domain (lower and upper bounds) over which to assess the "coverage".
If *domain* is `None`, then the domain is considered to be the extremities of the intervals
contained in *interval_array*
domain : :py:class:`tuple`, :class:`pandas.Interval`, :class:`pandas.IntervalIndex` or :class:`pandas.arrays.IntervalArray`, optional
Specifies the domain over which to calculate the "coverage". If *domain* is `None`,
then the domain is considered to be the extremities of the intervals contained in *interval_array*
If *domain* is a tuple then it should specify lower and upper bounds, and be equivalent to a
:class:`pandas.Interval`. If *domain* is a :class:`pandas.IntervalIndex` or :class:`pandas.arrays.IntervalArray`
then the intervals it contains define a possibly disconnected domain.
Returns
----------
Expand All @@ -627,6 +629,12 @@ def join_params(list_of_param_strings):
>>> piso.coverage(arr1, pd.Interval(-10, 10))
0.3
>>> domain = pd.arrays.IntervalArray.from_tuples(
... [(4,6), (7, 9)],
... )
>>> piso.coverage(arr1, domain)
0.5
"""


Expand Down
10 changes: 8 additions & 2 deletions piso/intervalarray.py
Original file line number Diff line number Diff line change
Expand Up @@ -173,8 +173,14 @@ def _get_domain_tuple(interval_array, domain):

@Appender(docstrings.coverage_docstring, join="\n", indents=1)
def coverage(interval_array, domain=None):
domain = _get_domain_tuple(interval_array, domain)
return _interval_x_to_stairs(interval_array).make_boolean().clip(*domain).mean()
stepfunction = _interval_x_to_stairs(interval_array).make_boolean()
if isinstance(domain, (pd.IntervalIndex, pd.arrays.IntervalArray)):
domain = _interval_x_to_stairs(domain)
result = stepfunction.where(domain).mean()
else:
domain = _get_domain_tuple(interval_array, domain)
result = stepfunction.clip(*domain).mean()
return result


@Appender(docstrings.complement_docstring, join="\n", indents=1)
Expand Down
11 changes: 10 additions & 1 deletion tests/test_single_interval_array.py
Original file line number Diff line number Diff line change
Expand Up @@ -496,7 +496,14 @@ def test_isdisjoint(interval_index, tuples, expected, closed, date_type, how):
)
@pytest.mark.parametrize(
"domain, expected",
[(None, 10 / 12), ((0, 10), 0.8), (pd.Interval(0, 10), 0.8), ((15, 20), 0)],
[
(None, 10 / 12),
((0, 10), 0.8),
(pd.Interval(0, 10), 0.8),
((15, 20), 0),
(pd.IntervalIndex.from_tuples([(0, 6), (10, 12)]), 1),
(pd.IntervalIndex.from_tuples([(6, 7), (9, 10)]), 0),
],
)
@pytest.mark.parametrize(
"closed",
Expand All @@ -507,6 +514,8 @@ def test_isdisjoint(interval_index, tuples, expected, closed, date_type, how):
["supplied", "accessor", "package"],
)
def test_coverage(interval_index, domain, expected, closed, how):
if hasattr(domain, "set_closed"):
domain = domain.set_closed(closed)
ia = make_ia1(interval_index, closed)
result = perform_op(
ia,
Expand Down

0 comments on commit 37a76c0

Please sign in to comment.