Skip to content

[ENH] Use default EA repr for IntervalArray #26316

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 23 commits into from
Sep 10, 2019
Merged
Show file tree
Hide file tree
Changes from 4 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
35 changes: 21 additions & 14 deletions pandas/core/arrays/interval.py
Original file line number Diff line number Diff line change
Expand Up @@ -116,9 +116,9 @@
``Interval`` objects:

>>> pd.arrays.IntervalArray([pd.Interval(0, 1), pd.Interval(1, 5)])
IntervalArray([(0, 1], (1, 5]],
closed='right',
dtype='interval[int64]')
<IntervalArray>
[(0, 1], (1, 5]]
Length: 2, closed: right, dtype: interval[int64]

It may also be constructed using one of the constructor
methods: :meth:`IntervalArray.from_arrays`,
Expand Down Expand Up @@ -843,14 +843,20 @@ def _format_data(self):
return summary

def __repr__(self):
tpl = textwrap.dedent("""\
{cls}({data},
{lead}closed='{closed}',
{lead}dtype='{dtype}')""")
return tpl.format(cls=self.__class__.__name__,
data=self._format_data(),
lead=' ' * len(self.__class__.__name__) + ' ',
closed=self.closed, dtype=self.dtype)
template = (
'{class_name}'
'{data}\n'
'Length: {length}, closed: {closed}, dtype: {dtype}'
)
# the short repr has no trailing newline, while the truncated
# repr does. So we include a newline in our template, and strip
# any trailing newlines from format_object_summary
data = self._format_data()
class_name = '<{}>\n'.format(self.__class__.__name__)
return template.format(class_name=class_name, data=data,
length=len(self),
closed=self.closed,
dtype=self.dtype)

def _format_space(self):
space = ' ' * (len(self.__class__.__name__) + 1)
Expand Down Expand Up @@ -1049,9 +1055,10 @@ def repeat(self, repeats, axis=None):
--------
>>> intervals = pd.%(qualname)s.from_tuples([(0, 1), (1, 3), (2, 4)])
>>> intervals
%(klass)s([(0, 1], (1, 3], (2, 4]],
closed='right',
dtype='interval[int64]')
<%(klass)s>
[(0, 1], (1, 3], (2, 4]]
Length: 3, closed: right, dtype: interval[int64]

>>> intervals.overlaps(pd.Interval(0.5, 1.5))
array([ True, True, False])

Expand Down
46 changes: 45 additions & 1 deletion pandas/core/indexes/interval.py
Original file line number Diff line number Diff line change
Expand Up @@ -1086,8 +1086,52 @@ def equals(self, other):
self.right.equals(other.right) and
self.closed == other.closed)

@Appender(_interval_shared_docs['overlaps'] % _index_doc_kwargs)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think there should be a way of reusing the main portion of the docstring, and appending in custom examples. Something similar to the constructor maybe?

@Appender(_interval_shared_docs['class'] % dict(
klass="IntervalIndex",
summary="Immutable index of intervals that are closed on the same side.",
name=_index_doc_kwargs['name'],
versionadded="0.20.0",
extra_attributes="is_overlapping\nvalues\n",
extra_methods="contains\n",
examples=textwrap.dedent("""\
Examples
--------
A new ``IntervalIndex`` is typically constructed using
:func:`interval_range`:
>>> pd.interval_range(start=0, end=5)
IntervalIndex([(0, 1], (1, 2], (2, 3], (3, 4], (4, 5]],
closed='right',
dtype='interval[int64]')
It may also be constructed using one of the constructor
methods: :meth:`IntervalIndex.from_arrays`,
:meth:`IntervalIndex.from_breaks`, and :meth:`IntervalIndex.from_tuples`.
See further examples in the doc strings of ``interval_range`` and the
mentioned constructor methods.
"""),

def overlaps(self, other):
"""
Check elementwise if an Interval overlaps the values in the
IntervalIndex.

Two intervals overlap if they share a common point, including closed
endpoints. Intervals that only have an open endpoint in common do not
overlap.

.. versionadded:: 0.24.0

Parameters
----------
other : Interval
Interval to check against for an overlap.

Returns
-------
ndarray
Boolean array positionally indicating where an overlap occurs.

See Also
--------
Interval.overlaps : Check whether two Interval objects overlap.

Examples
--------
>>> intervals = pd.IntervalIndex.from_tuples([(0, 1), (1, 3), (2, 4)])
>>> intervals
IntervalIndex([(0, 1], (1, 3], (2, 4]],
closed='right',
dtype='interval[int64]')

>>> intervals.overlaps(pd.Interval(0.5, 1.5))
array([ True, True, False])

Intervals that share closed endpoints overlap:

>>> intervals.overlaps(pd.Interval(1, 3, closed='left'))
array([ True, True, True])

Intervals that only have an open endpoint in common do not overlap:

>>> intervals.overlaps(pd.Interval(1, 2, closed='right'))
array([False, True, False])
"""
return self._data.overlaps(other)

def _setop(op_name, sort=None):
Expand Down
9 changes: 1 addition & 8 deletions pandas/tests/arrays/interval/test_interval.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
import pytest

import pandas as pd
from pandas import Index, Interval, IntervalIndex, date_range, timedelta_range
from pandas import Index, Interval, date_range, timedelta_range
from pandas.core.arrays import IntervalArray
import pandas.util.testing as tm

Expand Down Expand Up @@ -58,10 +58,3 @@ def test_set_na(self, left_right_dtypes):
expected = IntervalArray.from_arrays(expected_left, expected_right)

tm.assert_extension_array_equal(result, expected)


def test_repr_matches():
idx = IntervalIndex.from_breaks([1, 2, 3])
a = repr(idx)
b = repr(idx.values)
assert a.replace("Index", "Array") == b