Skip to content

Commit 09e4b78

Browse files
jbrockmendeljreback
authored andcommitted
BUG: Index.__new__ with Interval/Period data and object dtype (#30635)
1 parent 8105a7e commit 09e4b78

File tree

2 files changed

+43
-16
lines changed

2 files changed

+43
-16
lines changed

pandas/core/indexes/base.py

+13-7
Original file line numberDiff line numberDiff line change
@@ -295,11 +295,15 @@ def __new__(
295295
return CategoricalIndex(data, dtype=dtype, copy=copy, name=name, **kwargs)
296296

297297
# interval
298-
elif (
299-
is_interval_dtype(data) or is_interval_dtype(dtype)
300-
) and not is_object_dtype(dtype):
301-
closed = kwargs.get("closed", None)
302-
return IntervalIndex(data, dtype=dtype, name=name, copy=copy, closed=closed)
298+
elif is_interval_dtype(data) or is_interval_dtype(dtype):
299+
closed = kwargs.pop("closed", None)
300+
if is_dtype_equal(_o_dtype, dtype):
301+
return IntervalIndex(
302+
data, name=name, copy=copy, closed=closed, **kwargs
303+
).astype(object)
304+
return IntervalIndex(
305+
data, dtype=dtype, name=name, copy=copy, closed=closed, **kwargs
306+
)
303307

304308
elif (
305309
is_datetime64_any_dtype(data)
@@ -329,8 +333,10 @@ def __new__(
329333
else:
330334
return TimedeltaIndex(data, copy=copy, name=name, dtype=dtype, **kwargs)
331335

332-
elif is_period_dtype(data) and not is_object_dtype(dtype):
333-
return PeriodIndex(data, copy=copy, name=name, **kwargs)
336+
elif is_period_dtype(data) or is_period_dtype(dtype):
337+
if is_dtype_equal(_o_dtype, dtype):
338+
return PeriodIndex(data, copy=False, name=name, **kwargs).astype(object)
339+
return PeriodIndex(data, dtype=dtype, copy=copy, name=name, **kwargs)
334340

335341
# extension dtype
336342
elif is_extension_array_dtype(data) or is_extension_array_dtype(dtype):

pandas/tests/indexes/period/test_constructors.py

+30-9
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,11 @@
77

88
import pandas as pd
99
from pandas import Index, Period, PeriodIndex, Series, date_range, offsets, period_range
10-
import pandas.core.indexes.period as period
10+
from pandas.core.arrays import PeriodArray
1111
import pandas.util.testing as tm
1212

1313

1414
class TestPeriodIndex:
15-
def setup_method(self, method):
16-
pass
17-
1815
def test_construction_base_constructor(self):
1916
# GH 13664
2017
arr = [pd.Period("2011-01", freq="M"), pd.NaT, pd.Period("2011-03", freq="M")]
@@ -32,6 +29,30 @@ def test_construction_base_constructor(self):
3229
pd.Index(np.array(arr)), pd.Index(np.array(arr), dtype=object)
3330
)
3431

32+
def test_base_constructor_with_period_dtype(self):
33+
dtype = PeriodDtype("D")
34+
values = ["2011-01-01", "2012-03-04", "2014-05-01"]
35+
result = pd.Index(values, dtype=dtype)
36+
37+
expected = pd.PeriodIndex(values, dtype=dtype)
38+
tm.assert_index_equal(result, expected)
39+
40+
@pytest.mark.parametrize(
41+
"values_constructor", [list, np.array, PeriodIndex, PeriodArray._from_sequence]
42+
)
43+
def test_index_object_dtype(self, values_constructor):
44+
# Index(periods, dtype=object) is an Index (not an PeriodIndex)
45+
periods = [
46+
pd.Period("2011-01", freq="M"),
47+
pd.NaT,
48+
pd.Period("2011-03", freq="M"),
49+
]
50+
values = values_constructor(periods)
51+
result = Index(values, dtype=object)
52+
53+
assert type(result) is Index
54+
tm.assert_numpy_array_equal(result.values, np.array(values))
55+
3556
def test_constructor_use_start_freq(self):
3657
# GH #1118
3758
p = Period("4/2/2012", freq="B")
@@ -201,7 +222,7 @@ def test_constructor_dtype(self):
201222
assert res.dtype == "period[M]"
202223

203224
msg = "specified freq and dtype are different"
204-
with pytest.raises(period.IncompatibleFrequency, match=msg):
225+
with pytest.raises(IncompatibleFrequency, match=msg):
205226
PeriodIndex(["2011-01"], freq="M", dtype="period[D]")
206227

207228
def test_constructor_empty(self):
@@ -261,25 +282,25 @@ def test_constructor_pi_nat(self):
261282
def test_constructor_incompat_freq(self):
262283
msg = "Input has different freq=D from PeriodIndex\\(freq=M\\)"
263284

264-
with pytest.raises(period.IncompatibleFrequency, match=msg):
285+
with pytest.raises(IncompatibleFrequency, match=msg):
265286
PeriodIndex(
266287
[Period("2011-01", freq="M"), pd.NaT, Period("2011-01", freq="D")]
267288
)
268289

269-
with pytest.raises(period.IncompatibleFrequency, match=msg):
290+
with pytest.raises(IncompatibleFrequency, match=msg):
270291
PeriodIndex(
271292
np.array(
272293
[Period("2011-01", freq="M"), pd.NaT, Period("2011-01", freq="D")]
273294
)
274295
)
275296

276297
# first element is pd.NaT
277-
with pytest.raises(period.IncompatibleFrequency, match=msg):
298+
with pytest.raises(IncompatibleFrequency, match=msg):
278299
PeriodIndex(
279300
[pd.NaT, Period("2011-01", freq="M"), Period("2011-01", freq="D")]
280301
)
281302

282-
with pytest.raises(period.IncompatibleFrequency, match=msg):
303+
with pytest.raises(IncompatibleFrequency, match=msg):
283304
PeriodIndex(
284305
np.array(
285306
[pd.NaT, Period("2011-01", freq="M"), Period("2011-01", freq="D")]

0 commit comments

Comments
 (0)