Skip to content

Commit 96bf661

Browse files
makbigcjschendel
authored andcommitted
[ENH] Use default EA repr for IntervalArray (#26316)
1 parent e0c63b4 commit 96bf661

File tree

4 files changed

+267
-85
lines changed

4 files changed

+267
-85
lines changed

doc/source/whatsnew/v1.0.0.rst

+19-1
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,25 @@ Backwards incompatible API changes
3737
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
3838

3939
- :class:`pandas.core.groupby.GroupBy.transform` now raises on invalid operation names (:issue:`27489`).
40-
-
40+
- :class:`pandas.core.arrays.IntervalArray` adopts a new ``__repr__`` in accordance with other array classes (:issue:`25022`)
41+
42+
*pandas 0.25.x*
43+
44+
.. code-block:: ipython
45+
46+
In [1]: pd.arrays.IntervalArray.from_tuples([(0, 1), (2, 3)])
47+
Out[2]:
48+
IntervalArray([(0, 1], (2, 3]],
49+
closed='right',
50+
dtype='interval[int64]')
51+
52+
53+
*pandas 1.0.0*
54+
55+
.. ipython:: python
56+
57+
pd.arrays.IntervalArray.from_tuples([(0, 1), (2, 3)])
58+
4159
4260
.. _whatsnew_1000.api.other:
4361

pandas/core/arrays/interval.py

+137-73
Original file line numberDiff line numberDiff line change
@@ -129,9 +129,9 @@
129129
``Interval`` objects:
130130
131131
>>> pd.arrays.IntervalArray([pd.Interval(0, 1), pd.Interval(1, 5)])
132-
IntervalArray([(0, 1], (1, 5]],
133-
closed='right',
134-
dtype='interval[int64]')
132+
<IntervalArray>
133+
[(0, 1], (1, 5]]
134+
Length: 2, closed: right, dtype: interval[int64]
135135
136136
It may also be constructed using one of the constructor
137137
methods: :meth:`IntervalArray.from_arrays`,
@@ -248,9 +248,8 @@ def _from_factorized(cls, values, original):
248248
values = values.astype(original.dtype.subtype)
249249
return cls(values, closed=original.closed)
250250

251-
_interval_shared_docs[
252-
"from_breaks"
253-
] = """
251+
_interval_shared_docs["from_breaks"] = textwrap.dedent(
252+
"""
254253
Construct an %(klass)s from an array of splits.
255254
256255
Parameters
@@ -277,24 +276,34 @@ def _from_factorized(cls, values, original):
277276
%(klass)s.from_arrays : Construct from a left and right array.
278277
%(klass)s.from_tuples : Construct from a sequence of tuples.
279278
280-
Examples
281-
--------
282-
>>> pd.%(qualname)s.from_breaks([0, 1, 2, 3])
283-
%(klass)s([(0, 1], (1, 2], (2, 3]],
284-
closed='right',
285-
dtype='interval[int64]')
279+
%(examples)s\
286280
"""
281+
)
287282

288283
@classmethod
289-
@Appender(_interval_shared_docs["from_breaks"] % _shared_docs_kwargs)
284+
@Appender(
285+
_interval_shared_docs["from_breaks"]
286+
% dict(
287+
klass="IntervalArray",
288+
examples=textwrap.dedent(
289+
"""\
290+
Examples
291+
--------
292+
>>> pd.arrays.IntervalArray.from_breaks([0, 1, 2, 3])
293+
<IntervalArray>
294+
[(0, 1], (1, 2], (2, 3]]
295+
Length: 3, closed: right, dtype: interval[int64]
296+
"""
297+
),
298+
)
299+
)
290300
def from_breaks(cls, breaks, closed="right", copy=False, dtype=None):
291301
breaks = maybe_convert_platform_interval(breaks)
292302

293303
return cls.from_arrays(breaks[:-1], breaks[1:], closed, copy=copy, dtype=dtype)
294304

295-
_interval_shared_docs[
296-
"from_arrays"
297-
] = """
305+
_interval_shared_docs["from_arrays"] = textwrap.dedent(
306+
"""
298307
Construct from two arrays defining the left and right bounds.
299308
300309
Parameters
@@ -340,16 +349,25 @@ def from_breaks(cls, breaks, closed="right", copy=False, dtype=None):
340349
using an unsupported type for `left` or `right`. At the moment,
341350
'category', 'object', and 'string' subtypes are not supported.
342351
343-
Examples
344-
--------
345-
>>> %(klass)s.from_arrays([0, 1, 2], [1, 2, 3])
346-
%(klass)s([(0, 1], (1, 2], (2, 3]],
347-
closed='right',
348-
dtype='interval[int64]')
352+
%(examples)s\
349353
"""
354+
)
350355

351356
@classmethod
352-
@Appender(_interval_shared_docs["from_arrays"] % _shared_docs_kwargs)
357+
@Appender(
358+
_interval_shared_docs["from_arrays"]
359+
% dict(
360+
klass="IntervalArray",
361+
examples=textwrap.dedent(
362+
"""\
363+
>>> pd.arrays.IntervalArray.from_arrays([0, 1, 2], [1, 2, 3])
364+
<IntervalArray>
365+
[(0, 1], (1, 2], (2, 3]]
366+
Length: 3, closed: right, dtype: interval[int64]
367+
"""
368+
),
369+
)
370+
)
353371
def from_arrays(cls, left, right, closed="right", copy=False, dtype=None):
354372
left = maybe_convert_platform_interval(left)
355373
right = maybe_convert_platform_interval(right)
@@ -358,9 +376,8 @@ def from_arrays(cls, left, right, closed="right", copy=False, dtype=None):
358376
left, right, closed, copy=copy, dtype=dtype, verify_integrity=True
359377
)
360378

361-
_interval_shared_docs[
362-
"from_tuples"
363-
] = """
379+
_interval_shared_docs["from_tuples"] = textwrap.dedent(
380+
"""
364381
Construct an %(klass)s from an array-like of tuples.
365382
366383
Parameters
@@ -389,15 +406,27 @@ def from_arrays(cls, left, right, closed="right", copy=False, dtype=None):
389406
%(klass)s.from_breaks : Construct an %(klass)s from an array of
390407
splits.
391408
392-
Examples
393-
--------
394-
>>> pd.%(qualname)s.from_tuples([(0, 1), (1, 2)])
395-
%(klass)s([(0, 1], (1, 2]],
396-
closed='right', dtype='interval[int64]')
409+
%(examples)s\
397410
"""
411+
)
398412

399413
@classmethod
400-
@Appender(_interval_shared_docs["from_tuples"] % _shared_docs_kwargs)
414+
@Appender(
415+
_interval_shared_docs["from_tuples"]
416+
% dict(
417+
klass="IntervalArray",
418+
examples=textwrap.dedent(
419+
"""\
420+
Examples
421+
--------
422+
>>> pd.arrays.IntervalArray.from_tuples([(0, 1), (1, 2)])
423+
<IntervalArray>
424+
[(0, 1], (1, 2]]
425+
Length: 2, closed: right, dtype: interval[int64]
426+
"""
427+
),
428+
)
429+
)
401430
def from_tuples(cls, data, closed="right", copy=False, dtype=None):
402431
if len(data):
403432
left, right = [], []
@@ -832,16 +861,20 @@ def _format_data(self):
832861
return summary
833862

834863
def __repr__(self):
835-
tpl = textwrap.dedent(
836-
"""\
837-
{cls}({data},
838-
{lead}closed='{closed}',
839-
{lead}dtype='{dtype}')"""
864+
template = (
865+
"{class_name}"
866+
"{data}\n"
867+
"Length: {length}, closed: {closed}, dtype: {dtype}"
840868
)
841-
return tpl.format(
842-
cls=self.__class__.__name__,
843-
data=self._format_data(),
844-
lead=" " * len(self.__class__.__name__) + " ",
869+
# the short repr has no trailing newline, while the truncated
870+
# repr does. So we include a newline in our template, and strip
871+
# any trailing newlines from format_object_summary
872+
data = self._format_data()
873+
class_name = "<{}>\n".format(self.__class__.__name__)
874+
return template.format(
875+
class_name=class_name,
876+
data=data,
877+
length=len(self),
845878
closed=self.closed,
846879
dtype=self.dtype,
847880
)
@@ -874,9 +907,8 @@ def closed(self):
874907
"""
875908
return self._closed
876909

877-
_interval_shared_docs[
878-
"set_closed"
879-
] = """
910+
_interval_shared_docs["set_closed"] = textwrap.dedent(
911+
"""
880912
Return an %(klass)s identical to the current one, but closed on the
881913
specified side.
882914
@@ -892,20 +924,31 @@ def closed(self):
892924
-------
893925
new_index : %(klass)s
894926
927+
%(examples)s\
928+
"""
929+
)
930+
931+
@Appender(
932+
_interval_shared_docs["set_closed"]
933+
% dict(
934+
klass="IntervalArray",
935+
examples=textwrap.dedent(
936+
"""\
895937
Examples
896938
--------
897-
>>> index = pd.interval_range(0, 3)
939+
>>> index = pd.arrays.IntervalArray.from_breaks(range(4))
898940
>>> index
899-
IntervalIndex([(0, 1], (1, 2], (2, 3]],
900-
closed='right',
901-
dtype='interval[int64]')
941+
<IntervalArray>
942+
[(0, 1], (1, 2], (2, 3]]
943+
Length: 3, closed: right, dtype: interval[int64]
902944
>>> index.set_closed('both')
903-
IntervalIndex([[0, 1], [1, 2], [2, 3]],
904-
closed='both',
905-
dtype='interval[int64]')
945+
<IntervalArray>
946+
[[0, 1], [1, 2], [2, 3]]
947+
Length: 3, closed: both, dtype: interval[int64]
906948
"""
907-
908-
@Appender(_interval_shared_docs["set_closed"] % _shared_docs_kwargs)
949+
),
950+
)
951+
)
909952
def set_closed(self, closed):
910953
if closed not in _VALID_CLOSED:
911954
msg = "invalid option for 'closed': {closed}"
@@ -1028,9 +1071,8 @@ def repeat(self, repeats, axis=None):
10281071
right_repeat = self.right.repeat(repeats)
10291072
return self._shallow_copy(left=left_repeat, right=right_repeat)
10301073

1031-
_interval_shared_docs[
1032-
"contains"
1033-
] = """
1074+
_interval_shared_docs["contains"] = textwrap.dedent(
1075+
"""
10341076
Check elementwise if the Intervals contain the value.
10351077
10361078
Return a boolean mask whether the value is contained in the Intervals
@@ -1055,16 +1097,27 @@ def repeat(self, repeats, axis=None):
10551097
10561098
Examples
10571099
--------
1058-
>>> intervals = pd.%(qualname)s.from_tuples([(0, 1), (1, 3), (2, 4)])
1059-
>>> intervals
1060-
%(klass)s([(0, 1], (1, 3], (2, 4]],
1061-
closed='right',
1062-
dtype='interval[int64]')
1100+
%(examples)s
10631101
>>> intervals.contains(0.5)
10641102
array([ True, False, False])
10651103
"""
1104+
)
10661105

1067-
@Appender(_interval_shared_docs["contains"] % _shared_docs_kwargs)
1106+
@Appender(
1107+
_interval_shared_docs["contains"]
1108+
% dict(
1109+
klass="IntervalArray",
1110+
examples=textwrap.dedent(
1111+
"""\
1112+
>>> intervals = pd.arrays.IntervalArray.from_tuples([(0, 1), (1, 3), (2, 4)])
1113+
>>> intervals
1114+
<IntervalArray>
1115+
[(0, 1], (1, 3], (2, 4]]
1116+
Length: 3, closed: right, dtype: interval[int64]
1117+
"""
1118+
),
1119+
)
1120+
)
10681121
def contains(self, other):
10691122
if isinstance(other, Interval):
10701123
raise NotImplementedError("contains not implemented for two intervals")
@@ -1073,9 +1126,8 @@ def contains(self, other):
10731126
other < self.right if self.open_right else other <= self.right
10741127
)
10751128

1076-
_interval_shared_docs[
1077-
"overlaps"
1078-
] = """
1129+
_interval_shared_docs["overlaps"] = textwrap.dedent(
1130+
"""
10791131
Check elementwise if an Interval overlaps the values in the %(klass)s.
10801132
10811133
Two intervals overlap if they share a common point, including closed
@@ -1086,7 +1138,7 @@ def contains(self, other):
10861138
10871139
Parameters
10881140
----------
1089-
other : Interval
1141+
other : %(klass)s
10901142
Interval to check against for an overlap.
10911143
10921144
Returns
@@ -1100,11 +1152,7 @@ def contains(self, other):
11001152
11011153
Examples
11021154
--------
1103-
>>> intervals = pd.%(qualname)s.from_tuples([(0, 1), (1, 3), (2, 4)])
1104-
>>> intervals
1105-
%(klass)s([(0, 1], (1, 3], (2, 4]],
1106-
closed='right',
1107-
dtype='interval[int64]')
1155+
%(examples)s
11081156
>>> intervals.overlaps(pd.Interval(0.5, 1.5))
11091157
array([ True, True, False])
11101158
@@ -1117,9 +1165,25 @@ def contains(self, other):
11171165
11181166
>>> intervals.overlaps(pd.Interval(1, 2, closed='right'))
11191167
array([False, True, False])
1120-
"""
1168+
"""
1169+
)
11211170

1122-
@Appender(_interval_shared_docs["overlaps"] % _shared_docs_kwargs)
1171+
@Appender(
1172+
_interval_shared_docs["overlaps"]
1173+
% dict(
1174+
klass="IntervalArray",
1175+
examples=textwrap.dedent(
1176+
"""\
1177+
>>> data = [(0, 1), (1, 3), (2, 4)]
1178+
>>> intervals = pd.arrays.IntervalArray.from_tuples(data)
1179+
>>> intervals
1180+
<IntervalArray>
1181+
[(0, 1], (1, 3], (2, 4]]
1182+
Length: 3, closed: right, dtype: interval[int64]
1183+
"""
1184+
),
1185+
)
1186+
)
11231187
def overlaps(self, other):
11241188
if isinstance(other, (IntervalArray, ABCIntervalIndex)):
11251189
raise NotImplementedError

0 commit comments

Comments
 (0)