Skip to content

Commit 4d28445

Browse files
committed
Revert "ENH: consistency of input args for boundaries - pd.interval_range (pandas-dev#46355)"
This reverts commit 073b353.
1 parent 36a3d8e commit 4d28445

File tree

14 files changed

+53
-106
lines changed

14 files changed

+53
-106
lines changed

doc/source/user_guide/advanced.rst

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1082,14 +1082,14 @@ of :ref:`frequency aliases <timeseries.offset_aliases>` with datetime-like inter
10821082
10831083
pd.interval_range(start=pd.Timedelta("0 days"), periods=3, freq="9H")
10841084
1085-
Additionally, the ``inclusive`` parameter can be used to specify which side(s) the intervals
1086-
are closed on. Intervals are closed on the both side by default.
1085+
Additionally, the ``closed`` parameter can be used to specify which side(s) the intervals
1086+
are closed on. Intervals are closed on the right side by default.
10871087

10881088
.. ipython:: python
10891089
1090-
pd.interval_range(start=0, end=4, inclusive="both")
1090+
pd.interval_range(start=0, end=4, closed="both")
10911091
1092-
pd.interval_range(start=0, end=4, inclusive="neither")
1092+
pd.interval_range(start=0, end=4, closed="neither")
10931093
10941094
Specifying ``start``, ``end``, and ``periods`` will generate a range of evenly spaced
10951095
intervals from ``start`` to ``end`` inclusively, with ``periods`` number of elements

doc/source/whatsnew/v1.5.0.rst

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -821,7 +821,6 @@ Other Deprecations
821821
- Deprecated :attr:`Timedelta.freq` and :attr:`Timedelta.is_populated` (:issue:`46430`)
822822
- Deprecated :attr:`Timedelta.delta` (:issue:`46476`)
823823
- Deprecated passing arguments as positional in :meth:`DataFrame.any` and :meth:`Series.any` (:issue:`44802`)
824-
- Deprecated the ``closed`` argument in :meth:`interval_range` in favor of ``inclusive`` argument; In a future version passing ``closed`` will raise (:issue:`40245`)
825824
- Deprecated the methods :meth:`DataFrame.mad`, :meth:`Series.mad`, and the corresponding groupby methods (:issue:`11787`)
826825
- Deprecated positional arguments to :meth:`Index.join` except for ``other``, use keyword-only arguments instead of positional arguments (:issue:`46518`)
827826
- Deprecated positional arguments to :meth:`StringMethods.rsplit` and :meth:`StringMethods.split` except for ``pat``, use keyword-only arguments instead of positional arguments (:issue:`47423`)

pandas/core/indexes/interval.py

Lines changed: 12 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@
1212
Hashable,
1313
Literal,
1414
)
15-
import warnings
1615

1716
import numpy as np
1817

@@ -162,7 +161,7 @@ def _new_IntervalIndex(cls, d):
162161
A new ``IntervalIndex`` is typically constructed using
163162
:func:`interval_range`:
164163
165-
>>> pd.interval_range(start=0, end=5, inclusive="right")
164+
>>> pd.interval_range(start=0, end=5)
166165
IntervalIndex([(0, 1], (1, 2], (2, 3], (3, 4], (4, 5]],
167166
dtype='interval[int64, right]')
168167
@@ -445,7 +444,7 @@ def is_overlapping(self) -> bool:
445444
446445
Intervals that share closed endpoints overlap:
447446
448-
>>> index = pd.interval_range(0, 3, inclusive='both')
447+
>>> index = pd.interval_range(0, 3, closed='both')
449448
>>> index
450449
IntervalIndex([[0, 1], [1, 2], [2, 3]],
451450
dtype='interval[int64, both]')
@@ -454,7 +453,7 @@ def is_overlapping(self) -> bool:
454453
455454
Intervals that only have an open endpoint in common do not overlap:
456455
457-
>>> index = pd.interval_range(0, 3, inclusive='left')
456+
>>> index = pd.interval_range(0, 3, closed='left')
458457
>>> index
459458
IntervalIndex([[0, 1), [1, 2), [2, 3)],
460459
dtype='interval[int64, left]')
@@ -958,8 +957,7 @@ def interval_range(
958957
periods=None,
959958
freq=None,
960959
name: Hashable = None,
961-
closed: IntervalClosedType | lib.NoDefault = lib.no_default,
962-
inclusive: IntervalClosedType | None = None,
960+
closed: IntervalClosedType = "right",
963961
) -> IntervalIndex:
964962
"""
965963
Return a fixed frequency IntervalIndex.
@@ -982,14 +980,6 @@ def interval_range(
982980
Whether the intervals are closed on the left-side, right-side, both
983981
or neither.
984982
985-
.. deprecated:: 1.5.0
986-
Argument `closed` has been deprecated to standardize boundary inputs.
987-
Use `inclusive` instead, to set each bound as closed or open.
988-
inclusive : {"both", "neither", "left", "right"}, default "both"
989-
Include boundaries; Whether to set each bound as closed or open.
990-
991-
.. versionadded:: 1.5.0
992-
993983
Returns
994984
-------
995985
IntervalIndex
@@ -1012,14 +1002,14 @@ def interval_range(
10121002
--------
10131003
Numeric ``start`` and ``end`` is supported.
10141004
1015-
>>> pd.interval_range(start=0, end=5, inclusive="right")
1005+
>>> pd.interval_range(start=0, end=5)
10161006
IntervalIndex([(0, 1], (1, 2], (2, 3], (3, 4], (4, 5]],
10171007
dtype='interval[int64, right]')
10181008
10191009
Additionally, datetime-like input is also supported.
10201010
10211011
>>> pd.interval_range(start=pd.Timestamp('2017-01-01'),
1022-
... end=pd.Timestamp('2017-01-04'), inclusive="right")
1012+
... end=pd.Timestamp('2017-01-04'))
10231013
IntervalIndex([(2017-01-01, 2017-01-02], (2017-01-02, 2017-01-03],
10241014
(2017-01-03, 2017-01-04]],
10251015
dtype='interval[datetime64[ns], right]')
@@ -1028,56 +1018,33 @@ def interval_range(
10281018
endpoints of the individual intervals within the ``IntervalIndex``. For
10291019
numeric ``start`` and ``end``, the frequency must also be numeric.
10301020
1031-
>>> pd.interval_range(start=0, periods=4, freq=1.5, inclusive="right")
1021+
>>> pd.interval_range(start=0, periods=4, freq=1.5)
10321022
IntervalIndex([(0.0, 1.5], (1.5, 3.0], (3.0, 4.5], (4.5, 6.0]],
10331023
dtype='interval[float64, right]')
10341024
10351025
Similarly, for datetime-like ``start`` and ``end``, the frequency must be
10361026
convertible to a DateOffset.
10371027
10381028
>>> pd.interval_range(start=pd.Timestamp('2017-01-01'),
1039-
... periods=3, freq='MS', inclusive="right")
1029+
... periods=3, freq='MS')
10401030
IntervalIndex([(2017-01-01, 2017-02-01], (2017-02-01, 2017-03-01],
10411031
(2017-03-01, 2017-04-01]],
10421032
dtype='interval[datetime64[ns], right]')
10431033
10441034
Specify ``start``, ``end``, and ``periods``; the frequency is generated
10451035
automatically (linearly spaced).
10461036
1047-
>>> pd.interval_range(start=0, end=6, periods=4, inclusive="right")
1037+
>>> pd.interval_range(start=0, end=6, periods=4)
10481038
IntervalIndex([(0.0, 1.5], (1.5, 3.0], (3.0, 4.5], (4.5, 6.0]],
10491039
dtype='interval[float64, right]')
10501040
1051-
The ``inclusive`` parameter specifies which endpoints of the individual
1041+
The ``closed`` parameter specifies which endpoints of the individual
10521042
intervals within the ``IntervalIndex`` are closed.
10531043
1054-
>>> pd.interval_range(end=5, periods=4, inclusive='both')
1044+
>>> pd.interval_range(end=5, periods=4, closed='both')
10551045
IntervalIndex([[1, 2], [2, 3], [3, 4], [4, 5]],
10561046
dtype='interval[int64, both]')
10571047
"""
1058-
if inclusive is not None and closed is not lib.no_default:
1059-
raise ValueError(
1060-
"Deprecated argument `closed` cannot be passed "
1061-
"if argument `inclusive` is not None"
1062-
)
1063-
elif closed is not lib.no_default:
1064-
warnings.warn(
1065-
"Argument `closed` is deprecated in favor of `inclusive`.",
1066-
FutureWarning,
1067-
stacklevel=2,
1068-
)
1069-
if closed is None:
1070-
inclusive = "both"
1071-
elif closed in ("both", "neither", "left", "right"):
1072-
inclusive = closed
1073-
else:
1074-
raise ValueError(
1075-
"Argument `closed` has to be either"
1076-
"'both', 'neither', 'left' or 'right'"
1077-
)
1078-
elif inclusive is None:
1079-
inclusive = "both"
1080-
10811048
start = maybe_box_datetimelike(start)
10821049
end = maybe_box_datetimelike(end)
10831050
endpoint = start if start is not None else end
@@ -1150,4 +1117,4 @@ def interval_range(
11501117
else:
11511118
breaks = timedelta_range(start=start, end=end, periods=periods, freq=freq)
11521119

1153-
return IntervalIndex.from_breaks(breaks, name=name, closed=inclusive)
1120+
return IntervalIndex.from_breaks(breaks, name=name, closed=closed)

pandas/tests/frame/methods/test_round.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -210,7 +210,7 @@ def test_round_nonunique_categorical(self):
210210

211211
def test_round_interval_category_columns(self):
212212
# GH#30063
213-
columns = pd.CategoricalIndex(pd.interval_range(0, 2, inclusive="right"))
213+
columns = pd.CategoricalIndex(pd.interval_range(0, 2))
214214
df = DataFrame([[0.66, 1.1], [0.3, 0.25]], columns=columns)
215215

216216
result = df.round()

pandas/tests/groupby/aggregate/test_cython.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -216,7 +216,7 @@ def test_cython_agg_empty_buckets_nanops(observed):
216216
result = df.groupby(pd.cut(df["a"], grps), observed=observed)._cython_agg_general(
217217
"sum", alt=None, numeric_only=True
218218
)
219-
intervals = pd.interval_range(0, 20, freq=5, inclusive="right")
219+
intervals = pd.interval_range(0, 20, freq=5)
220220
expected = DataFrame(
221221
{"a": [0, 0, 36, 0]},
222222
index=pd.CategoricalIndex(intervals, name="a", ordered=True),

pandas/tests/indexes/interval/test_astype.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,7 @@ def test_subtype_integer(self, subtype_start, subtype_end):
117117
@pytest.mark.xfail(reason="GH#15832")
118118
def test_subtype_integer_errors(self):
119119
# int64 -> uint64 fails with negative values
120-
index = interval_range(-10, 10, inclusive="right")
120+
index = interval_range(-10, 10)
121121
dtype = IntervalDtype("uint64", "right")
122122

123123
# Until we decide what the exception message _should_ be, we
@@ -133,7 +133,7 @@ class TestFloatSubtype(AstypeTests):
133133
"""Tests specific to IntervalIndex with float subtype"""
134134

135135
indexes = [
136-
interval_range(-10.0, 10.0, inclusive="neither"),
136+
interval_range(-10.0, 10.0, closed="neither"),
137137
IntervalIndex.from_arrays(
138138
[-1.5, np.nan, 0.0, 0.0, 1.5], [-0.5, np.nan, 1.0, 1.0, 3.0], closed="both"
139139
),
@@ -170,7 +170,7 @@ def test_subtype_integer_with_non_integer_borders(self, subtype):
170170

171171
def test_subtype_integer_errors(self):
172172
# float64 -> uint64 fails with negative values
173-
index = interval_range(-10.0, 10.0, inclusive="right")
173+
index = interval_range(-10.0, 10.0)
174174
dtype = IntervalDtype("uint64", "right")
175175
msg = re.escape(
176176
"Cannot convert interval[float64, right] to interval[uint64, right]; "
@@ -191,10 +191,10 @@ class TestDatetimelikeSubtype(AstypeTests):
191191
"""Tests specific to IntervalIndex with datetime-like subtype"""
192192

193193
indexes = [
194-
interval_range(Timestamp("2018-01-01"), periods=10, inclusive="neither"),
194+
interval_range(Timestamp("2018-01-01"), periods=10, closed="neither"),
195195
interval_range(Timestamp("2018-01-01"), periods=10).insert(2, NaT),
196196
interval_range(Timestamp("2018-01-01", tz="US/Eastern"), periods=10),
197-
interval_range(Timedelta("0 days"), periods=10, inclusive="both"),
197+
interval_range(Timedelta("0 days"), periods=10, closed="both"),
198198
interval_range(Timedelta("0 days"), periods=10).insert(2, NaT),
199199
]
200200

pandas/tests/indexes/interval/test_interval.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -167,10 +167,10 @@ def test_delete(self, closed):
167167
@pytest.mark.parametrize(
168168
"data",
169169
[
170-
interval_range(0, periods=10, inclusive="neither"),
171-
interval_range(1.7, periods=8, freq=2.5, inclusive="both"),
172-
interval_range(Timestamp("20170101"), periods=12, inclusive="left"),
173-
interval_range(Timedelta("1 day"), periods=6, inclusive="right"),
170+
interval_range(0, periods=10, closed="neither"),
171+
interval_range(1.7, periods=8, freq=2.5, closed="both"),
172+
interval_range(Timestamp("20170101"), periods=12, closed="left"),
173+
interval_range(Timedelta("1 day"), periods=6, closed="right"),
174174
],
175175
)
176176
def test_insert(self, data):
@@ -868,9 +868,9 @@ def test_nbytes(self):
868868
@pytest.mark.parametrize("new_closed", ["left", "right", "both", "neither"])
869869
def test_set_closed(self, name, closed, new_closed):
870870
# GH 21670
871-
index = interval_range(0, 5, inclusive=closed, name=name)
871+
index = interval_range(0, 5, closed=closed, name=name)
872872
result = index.set_closed(new_closed)
873-
expected = interval_range(0, 5, inclusive=new_closed, name=name)
873+
expected = interval_range(0, 5, closed=new_closed, name=name)
874874
tm.assert_index_equal(result, expected)
875875

876876
@pytest.mark.parametrize("bad_closed", ["foo", 10, "LEFT", True, False])

pandas/tests/indexes/interval/test_interval_range.py

Lines changed: 14 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -34,25 +34,25 @@ def test_constructor_numeric(self, closed, name, freq, periods):
3434

3535
# defined from start/end/freq
3636
result = interval_range(
37-
start=start, end=end, freq=freq, name=name, inclusive=closed
37+
start=start, end=end, freq=freq, name=name, closed=closed
3838
)
3939
tm.assert_index_equal(result, expected)
4040

4141
# defined from start/periods/freq
4242
result = interval_range(
43-
start=start, periods=periods, freq=freq, name=name, inclusive=closed
43+
start=start, periods=periods, freq=freq, name=name, closed=closed
4444
)
4545
tm.assert_index_equal(result, expected)
4646

4747
# defined from end/periods/freq
4848
result = interval_range(
49-
end=end, periods=periods, freq=freq, name=name, inclusive=closed
49+
end=end, periods=periods, freq=freq, name=name, closed=closed
5050
)
5151
tm.assert_index_equal(result, expected)
5252

5353
# GH 20976: linspace behavior defined from start/end/periods
5454
result = interval_range(
55-
start=start, end=end, periods=periods, name=name, inclusive=closed
55+
start=start, end=end, periods=periods, name=name, closed=closed
5656
)
5757
tm.assert_index_equal(result, expected)
5858

@@ -67,19 +67,19 @@ def test_constructor_timestamp(self, closed, name, freq, periods, tz):
6767

6868
# defined from start/end/freq
6969
result = interval_range(
70-
start=start, end=end, freq=freq, name=name, inclusive=closed
70+
start=start, end=end, freq=freq, name=name, closed=closed
7171
)
7272
tm.assert_index_equal(result, expected)
7373

7474
# defined from start/periods/freq
7575
result = interval_range(
76-
start=start, periods=periods, freq=freq, name=name, inclusive=closed
76+
start=start, periods=periods, freq=freq, name=name, closed=closed
7777
)
7878
tm.assert_index_equal(result, expected)
7979

8080
# defined from end/periods/freq
8181
result = interval_range(
82-
end=end, periods=periods, freq=freq, name=name, inclusive=closed
82+
end=end, periods=periods, freq=freq, name=name, closed=closed
8383
)
8484
tm.assert_index_equal(result, expected)
8585

@@ -88,7 +88,7 @@ def test_constructor_timestamp(self, closed, name, freq, periods, tz):
8888
# matches expected only for non-anchored offsets and tz naive
8989
# (anchored/DST transitions cause unequal spacing in expected)
9090
result = interval_range(
91-
start=start, end=end, periods=periods, name=name, inclusive=closed
91+
start=start, end=end, periods=periods, name=name, closed=closed
9292
)
9393
tm.assert_index_equal(result, expected)
9494

@@ -102,25 +102,25 @@ def test_constructor_timedelta(self, closed, name, freq, periods):
102102

103103
# defined from start/end/freq
104104
result = interval_range(
105-
start=start, end=end, freq=freq, name=name, inclusive=closed
105+
start=start, end=end, freq=freq, name=name, closed=closed
106106
)
107107
tm.assert_index_equal(result, expected)
108108

109109
# defined from start/periods/freq
110110
result = interval_range(
111-
start=start, periods=periods, freq=freq, name=name, inclusive=closed
111+
start=start, periods=periods, freq=freq, name=name, closed=closed
112112
)
113113
tm.assert_index_equal(result, expected)
114114

115115
# defined from end/periods/freq
116116
result = interval_range(
117-
end=end, periods=periods, freq=freq, name=name, inclusive=closed
117+
end=end, periods=periods, freq=freq, name=name, closed=closed
118118
)
119119
tm.assert_index_equal(result, expected)
120120

121121
# GH 20976: linspace behavior defined from start/end/periods
122122
result = interval_range(
123-
start=start, end=end, periods=periods, name=name, inclusive=closed
123+
start=start, end=end, periods=periods, name=name, closed=closed
124124
)
125125
tm.assert_index_equal(result, expected)
126126

@@ -163,9 +163,7 @@ def test_no_invalid_float_truncation(self, start, end, freq):
163163
breaks = [0.5, 2.0, 3.5, 5.0, 6.5]
164164
expected = IntervalIndex.from_breaks(breaks)
165165

166-
result = interval_range(
167-
start=start, end=end, periods=4, freq=freq, inclusive="right"
168-
)
166+
result = interval_range(start=start, end=end, periods=4, freq=freq)
169167
tm.assert_index_equal(result, expected)
170168

171169
@pytest.mark.parametrize(
@@ -186,7 +184,7 @@ def test_no_invalid_float_truncation(self, start, end, freq):
186184
def test_linspace_dst_transition(self, start, mid, end):
187185
# GH 20976: linspace behavior defined from start/end/periods
188186
# accounts for the hour gained/lost during DST transition
189-
result = interval_range(start=start, end=end, periods=2, inclusive="right")
187+
result = interval_range(start=start, end=end, periods=2)
190188
expected = IntervalIndex.from_breaks([start, mid, end])
191189
tm.assert_index_equal(result, expected)
192190

@@ -355,17 +353,3 @@ def test_errors(self):
355353
msg = "Start and end cannot both be tz-aware with different timezones"
356354
with pytest.raises(TypeError, match=msg):
357355
interval_range(start=start, end=end)
358-
359-
def test_interval_range_error_and_warning(self):
360-
# GH 40245
361-
362-
msg = (
363-
"Deprecated argument `closed` cannot "
364-
"be passed if argument `inclusive` is not None"
365-
)
366-
with pytest.raises(ValueError, match=msg):
367-
interval_range(end=5, periods=4, closed="both", inclusive="both")
368-
369-
msg = "Argument `closed` is deprecated in favor of `inclusive`"
370-
with tm.assert_produces_warning(FutureWarning, match=msg):
371-
interval_range(end=5, periods=4, closed="right")

pandas/tests/indexes/interval/test_setops.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -194,7 +194,7 @@ def test_set_incompatible_types(self, closed, op_name, sort):
194194
tm.assert_index_equal(result, expected)
195195

196196
# GH 19016: incompatible dtypes -> cast to object
197-
other = interval_range(Timestamp("20180101"), periods=9, inclusive=closed)
197+
other = interval_range(Timestamp("20180101"), periods=9, closed=closed)
198198
expected = getattr(index.astype(object), op_name)(other, sort=sort)
199199
if op_name == "difference":
200200
expected = index

0 commit comments

Comments
 (0)