Skip to content

Commit d74ac70

Browse files
jschendeljreback
authored andcommitted
CLN/DOC: Interval and IntervalIndex classes (pandas-dev#18585)
1 parent 1eedcf6 commit d74ac70

File tree

2 files changed

+205
-117
lines changed

2 files changed

+205
-117
lines changed

pandas/_libs/interval.pyx

+72-42
Original file line numberDiff line numberDiff line change
@@ -14,30 +14,46 @@ import numbers
1414
_VALID_CLOSED = frozenset(['left', 'right', 'both', 'neither'])
1515

1616

17-
cdef class IntervalMixin:
18-
property closed_left:
19-
def __get__(self):
20-
return self.closed == 'left' or self.closed == 'both'
21-
22-
property closed_right:
23-
def __get__(self):
24-
return self.closed == 'right' or self.closed == 'both'
25-
26-
property open_left:
27-
def __get__(self):
28-
return not self.closed_left
29-
30-
property open_right:
31-
def __get__(self):
32-
return not self.closed_right
33-
34-
property mid:
35-
def __get__(self):
36-
try:
37-
return 0.5 * (self.left + self.right)
38-
except TypeError:
39-
# datetime safe version
40-
return self.left + 0.5 * (self.right - self.left)
17+
cdef class IntervalMixin(object):
18+
19+
@property
20+
def closed_left(self):
21+
"""
22+
Return True if the Interval is closed on the left-side, else False
23+
"""
24+
return self.closed in ('left', 'both')
25+
26+
@property
27+
def closed_right(self):
28+
"""
29+
Return True if the Interval is closed on the right-side, else False
30+
"""
31+
return self.closed in ('right', 'both')
32+
33+
@property
34+
def open_left(self):
35+
"""
36+
Return True if the Interval is open on the left-side, else False
37+
"""
38+
return not self.closed_left
39+
40+
@property
41+
def open_right(self):
42+
"""
43+
Return True if the Interval is open on the right-side, else False
44+
"""
45+
return not self.closed_right
46+
47+
@property
48+
def mid(self):
49+
"""
50+
Return the midpoint of the Interval
51+
"""
52+
try:
53+
return 0.5 * (self.left + self.right)
54+
except TypeError:
55+
# datetime safe version
56+
return self.left + 0.5 * (self.right - self.left)
4157

4258

4359
cdef _interval_like(other):
@@ -55,12 +71,12 @@ cdef class Interval(IntervalMixin):
5571
Parameters
5672
----------
5773
left : value
58-
Left bound for interval.
74+
Left bound for the interval
5975
right : value
60-
Right bound for interval.
61-
closed : {'left', 'right', 'both', 'neither'}
76+
Right bound for the interval
77+
closed : {'left', 'right', 'both', 'neither'}, default 'right'
6278
Whether the interval is closed on the left-side, right-side, both or
63-
neither. Defaults to 'right'.
79+
neither
6480
6581
Examples
6682
--------
@@ -77,20 +93,30 @@ cdef class Interval(IntervalMixin):
7793
7894
See Also
7995
--------
80-
IntervalIndex : an Index of ``interval`` s that are all closed on the same
81-
side.
82-
cut, qcut : convert arrays of continuous data into categoricals/series of
83-
``Interval``.
96+
IntervalIndex : An Index of Interval objects that are all closed on the
97+
same side.
98+
cut, qcut : Convert arrays of continuous data into Categoricals/Series of
99+
Interval.
84100
"""
85101

86-
cdef readonly object left, right
102+
cdef readonly object left
103+
"""Left bound for the interval"""
104+
105+
cdef readonly object right
106+
"""Right bound for the interval"""
107+
87108
cdef readonly str closed
109+
"""
110+
Whether the interval is closed on the left-side, right-side, both or
111+
neither
112+
"""
88113

89114
def __init__(self, left, right, str closed='right'):
90115
# note: it is faster to just do these checks than to use a special
91116
# constructor (__cinit__/__new__) to avoid them
92117
if closed not in _VALID_CLOSED:
93-
raise ValueError("invalid option for 'closed': %s" % closed)
118+
msg = "invalid option for 'closed': {closed}".format(closed=closed)
119+
raise ValueError(msg)
94120
if not left <= right:
95121
raise ValueError('left side of interval must be <= right side')
96122
self.left = left
@@ -122,10 +148,11 @@ cdef class Interval(IntervalMixin):
122148
if op == Py_EQ or op == Py_NE:
123149
return NotImplemented
124150
else:
151+
name = type(self).__name__
152+
other = type(other).__name__
125153
op_str = {Py_LT: '<', Py_LE: '<=', Py_GT: '>', Py_GE: '>='}[op]
126-
raise TypeError(
127-
'unorderable types: %s() %s %s()' %
128-
(type(self).__name__, op_str, type(other).__name__))
154+
raise TypeError('unorderable types: {name}() {op} {other}()'
155+
.format(name=name, op=op_str, other=other))
129156

130157
def __reduce__(self):
131158
args = (self.left, self.right, self.closed)
@@ -145,15 +172,18 @@ cdef class Interval(IntervalMixin):
145172
def __repr__(self):
146173

147174
left, right = self._repr_base()
148-
return ('%s(%r, %r, closed=%r)' %
149-
(type(self).__name__, left, right, self.closed))
175+
name = type(self).__name__
176+
repr_str = '{name}({left!r}, {right!r}, closed={closed!r})'.format(
177+
name=name, left=left, right=right, closed=self.closed)
178+
return repr_str
150179

151180
def __str__(self):
152181

153182
left, right = self._repr_base()
154183
start_symbol = '[' if self.closed_left else '('
155184
end_symbol = ']' if self.closed_right else ')'
156-
return '%s%s, %s%s' % (start_symbol, left, right, end_symbol)
185+
return '{start}{left}, {right}{end}'.format(
186+
start=start_symbol, left=left, right=right, end=end_symbol)
157187

158188
def __add__(self, y):
159189
if isinstance(y, numbers.Number):
@@ -222,8 +252,8 @@ cpdef intervals_to_interval_bounds(ndarray intervals):
222252
continue
223253

224254
if not isinstance(interval, Interval):
225-
raise TypeError("type {} with value {} is not an interval".format(
226-
type(interval), interval))
255+
raise TypeError("type {typ} with value {iv} is not an interval"
256+
.format(typ=type(interval), iv=interval))
227257

228258
left[i] = interval.left
229259
right[i] = interval.right

0 commit comments

Comments
 (0)