Skip to content

ENH: Add set_closed method to IntervalIndex #21711

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jul 3, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions doc/source/api.rst
Original file line number Diff line number Diff line change
Expand Up @@ -1642,6 +1642,7 @@ IntervalIndex Components
IntervalIndex.is_non_overlapping_monotonic
IntervalIndex.get_loc
IntervalIndex.get_indexer
IntervalIndex.set_closed


.. _api.multiindex:
Expand Down
1 change: 1 addition & 0 deletions doc/source/whatsnew/v0.24.0.txt
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ Other Enhancements
(:issue:`21627`)
- New method :meth:`HDFStore.walk` will recursively walk the group hierarchy of an HDF5 file (:issue:`10932`)
- :meth:`Series.nlargest`, :meth:`Series.nsmallest`, :meth:`DataFrame.nlargest`, and :meth:`DataFrame.nsmallest` now accept the value ``"all"`` for the ``keep` argument. This keeps all ties for the nth largest/smallest value (:issue:`16818`)
- :class:`IntervalIndex` has gained the :meth:`~IntervalIndex.set_closed` method to change the existing ``closed`` value (:issue:`21670`)
-

.. _whatsnew_0240.api_breaking:
Expand Down
36 changes: 36 additions & 0 deletions pandas/core/indexes/interval.py
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,7 @@ class IntervalIndex(IntervalMixin, Index):
from_tuples
get_indexer
get_loc
set_closed

Examples
---------
Expand Down Expand Up @@ -708,6 +709,41 @@ def closed(self):
"""
return self._closed

def set_closed(self, closed):
"""
Return an IntervalIndex identical to the current one, but closed on the
specified side

.. versionadded:: 0.24.0

Parameters
----------
closed : {'left', 'right', 'both', 'neither'}
Whether the intervals are closed on the left-side, right-side, both
or neither.

Returns
-------
new_index : IntervalIndex

Examples
--------
>>> index = pd.interval_range(0, 3)
>>> index
IntervalIndex([(0, 1], (1, 2], (2, 3]]
closed='right',
dtype='interval[int64]')
>>> index.set_closed('both')
IntervalIndex([[0, 1], [1, 2], [2, 3]]
closed='both',
dtype='interval[int64]')
"""
if closed not in _VALID_CLOSED:
msg = "invalid option for 'closed': {closed}"
raise ValueError(msg.format(closed=closed))

return self._shallow_copy(closed=closed)

@property
def length(self):
"""
Expand Down
17 changes: 17 additions & 0 deletions pandas/tests/indexes/interval/test_interval.py
Original file line number Diff line number Diff line change
Expand Up @@ -977,3 +977,20 @@ def test_to_tuples_na(self, tuples, na_tuple):
assert all(isna(x) for x in result_na)
else:
assert isna(result_na)

@pytest.mark.parametrize('new_closed', [
'left', 'right', 'both', 'neither'])
def test_set_closed(self, name, closed, new_closed):
# GH 21670
index = interval_range(0, 5, closed=closed, name=name)
result = index.set_closed(new_closed)
expected = interval_range(0, 5, closed=new_closed, name=name)
tm.assert_index_equal(result, expected)

@pytest.mark.parametrize('bad_closed', ['foo', 10, 'LEFT', True, False])
def test_set_closed_errors(self, bad_closed):
# GH 21670
index = interval_range(0, 5)
msg = "invalid option for 'closed': {closed}".format(closed=bad_closed)
with tm.assert_raises_regex(ValueError, msg):
index.set_closed(bad_closed)