Skip to content

Commit cffcfed

Browse files
authored
BUG: interval_range with float step (#54477)
1 parent 3522b41 commit cffcfed

File tree

3 files changed

+23
-12
lines changed

3 files changed

+23
-12
lines changed

doc/source/whatsnew/v2.1.0.rst

+1
Original file line numberDiff line numberDiff line change
@@ -737,6 +737,7 @@ Interval
737737
^^^^^^^^
738738
- :meth:`IntervalIndex.get_indexer` and :meth:`IntervalIndex.get_indexer_nonunique` raising if ``target`` is read-only array (:issue:`53703`)
739739
- Bug in :class:`IntervalDtype` where the object could be kept alive when deleted (:issue:`54184`)
740+
- Bug in :func:`interval_range` where a float ``step`` would produce incorrect intervals from floating point artifacts (:issue:`54477`)
740741

741742
Indexing
742743
^^^^^^^^

pandas/core/indexes/interval.py

+12-12
Original file line numberDiff line numberDiff line change
@@ -1121,19 +1121,19 @@ def interval_range(
11211121
breaks: np.ndarray | TimedeltaIndex | DatetimeIndex
11221122

11231123
if is_number(endpoint):
1124-
# force consistency between start/end/freq (lower end if freq skips it)
11251124
if com.all_not_none(start, end, freq):
1126-
end -= (end - start) % freq
1127-
1128-
# compute the period/start/end if unspecified (at most one)
1129-
if periods is None:
1130-
periods = int((end - start) // freq) + 1
1131-
elif start is None:
1132-
start = end - (periods - 1) * freq
1133-
elif end is None:
1134-
end = start + (periods - 1) * freq
1135-
1136-
breaks = np.linspace(start, end, periods)
1125+
# 0.1 ensures we capture end
1126+
breaks = np.arange(start, end + (freq * 0.1), freq)
1127+
else:
1128+
# compute the period/start/end if unspecified (at most one)
1129+
if periods is None:
1130+
periods = int((end - start) // freq) + 1
1131+
elif start is None:
1132+
start = end - (periods - 1) * freq
1133+
elif end is None:
1134+
end = start + (periods - 1) * freq
1135+
1136+
breaks = np.linspace(start, end, periods)
11371137
if all(is_integer(x) for x in com.not_none(start, end, freq)):
11381138
# np.linspace always produces float output
11391139

pandas/tests/indexes/interval/test_interval_range.py

+10
Original file line numberDiff line numberDiff line change
@@ -353,3 +353,13 @@ def test_errors(self):
353353
msg = "Start and end cannot both be tz-aware with different timezones"
354354
with pytest.raises(TypeError, match=msg):
355355
interval_range(start=start, end=end)
356+
357+
def test_float_freq(self):
358+
# GH 54477
359+
result = interval_range(0, 1, freq=0.1)
360+
expected = IntervalIndex.from_breaks([0 + 0.1 * n for n in range(11)])
361+
tm.assert_index_equal(result, expected)
362+
363+
result = interval_range(0, 1, freq=0.6)
364+
expected = IntervalIndex.from_breaks([0, 0.6])
365+
tm.assert_index_equal(result, expected)

0 commit comments

Comments
 (0)