Skip to content

Commit 2e5cb98

Browse files
committed
Address invalid lengths
1 parent a014151 commit 2e5cb98

File tree

4 files changed

+37
-2
lines changed

4 files changed

+37
-2
lines changed

pandas/_libs/interval.pyx

+6-1
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,12 @@ cdef class IntervalMixin(object):
5959
@property
6060
def length(self):
6161
"""Return the length of the Interval"""
62-
return self.right - self.left
62+
try:
63+
return self.right - self.left
64+
except TypeError:
65+
# length not defined for some types, e.g. string
66+
msg = 'cannot compute length between {left} and {right}'
67+
raise TypeError(msg.format(left=self.left, right=self.right))
6368

6469

6570
cdef _interval_like(other):

pandas/core/indexes/interval.py

+7-1
Original file line numberDiff line numberDiff line change
@@ -605,7 +605,13 @@ def length(self):
605605
Return an Index with entries denoting the length of each Interval in
606606
the IntervalIndex
607607
"""
608-
return self.right - self.left
608+
try:
609+
return self.right - self.left
610+
except TypeError:
611+
# length not defined for some types, e.g. string
612+
msg = ('IntervalIndex contains Intervals without defined length, '
613+
'e.g. Intervals with string endpoints')
614+
raise TypeError(msg)
609615

610616
def __len__(self):
611617
return len(self.left)

pandas/tests/indexes/test_interval.py

+11
Original file line numberDiff line numberDiff line change
@@ -300,6 +300,17 @@ def test_length(self, closed, breaks):
300300
expected = Index(iv.length if notna(iv) else iv for iv in index)
301301
tm.assert_index_equal(result, expected)
302302

303+
@pytest.mark.parametrize('breaks', [
304+
list('abcdefgh'),
305+
lzip(range(10), range(1, 11)),
306+
[['A', 'B'], ['a', 'b'], ['c', 'd'], ['e', 'f']],
307+
[Interval(0, 1), Interval(1, 2), Interval(3, 4), Interval(4, 5)]])
308+
def test_length_errors(self, closed, breaks):
309+
index = IntervalIndex.from_breaks(breaks)
310+
msg = 'IntervalIndex contains Intervals without defined length'
311+
with tm.assert_raises_regex(TypeError, msg):
312+
index.length
313+
303314
def test_with_nans(self, closed):
304315
index = self.create_index(closed=closed)
305316
assert not index.hasnans

pandas/tests/scalar/test_interval.py

+13
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,19 @@ def test_length_timestamp(self, tz, left, right, expected):
9797
expected = Timedelta(expected)
9898
assert result == expected
9999

100+
@pytest.mark.parametrize('left, right', [
101+
('a', 'z'),
102+
(('a', 'b'), ('c', 'd')),
103+
(list('AB'), list('ab')),
104+
(Interval(0, 1), Interval(1, 2))])
105+
def test_length_errors(self, left, right):
106+
# GH 18789
107+
iv = Interval(left, right)
108+
msg = 'cannot compute length between {left} and {right}'.format(
109+
left=left, right=right)
110+
with tm.assert_raises_regex(TypeError, msg):
111+
iv.length
112+
100113
def test_math_add(self, interval):
101114
expected = Interval(1, 2)
102115
actual = interval + 1

0 commit comments

Comments
 (0)