Skip to content

Commit

Permalink
BUG: Index.__new__ with Interval/Period data and object dtype (#30635)
Browse files Browse the repository at this point in the history
  • Loading branch information
jbrockmendel authored and jreback committed Jan 3, 2020
1 parent 8105a7e commit 09e4b78
Show file tree
Hide file tree
Showing 2 changed files with 43 additions and 16 deletions.
20 changes: 13 additions & 7 deletions pandas/core/indexes/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -295,11 +295,15 @@ def __new__(
return CategoricalIndex(data, dtype=dtype, copy=copy, name=name, **kwargs)

# interval
elif (
is_interval_dtype(data) or is_interval_dtype(dtype)
) and not is_object_dtype(dtype):
closed = kwargs.get("closed", None)
return IntervalIndex(data, dtype=dtype, name=name, copy=copy, closed=closed)
elif is_interval_dtype(data) or is_interval_dtype(dtype):
closed = kwargs.pop("closed", None)
if is_dtype_equal(_o_dtype, dtype):
return IntervalIndex(
data, name=name, copy=copy, closed=closed, **kwargs
).astype(object)
return IntervalIndex(
data, dtype=dtype, name=name, copy=copy, closed=closed, **kwargs
)

elif (
is_datetime64_any_dtype(data)
Expand Down Expand Up @@ -329,8 +333,10 @@ def __new__(
else:
return TimedeltaIndex(data, copy=copy, name=name, dtype=dtype, **kwargs)

elif is_period_dtype(data) and not is_object_dtype(dtype):
return PeriodIndex(data, copy=copy, name=name, **kwargs)
elif is_period_dtype(data) or is_period_dtype(dtype):
if is_dtype_equal(_o_dtype, dtype):
return PeriodIndex(data, copy=False, name=name, **kwargs).astype(object)
return PeriodIndex(data, dtype=dtype, copy=copy, name=name, **kwargs)

# extension dtype
elif is_extension_array_dtype(data) or is_extension_array_dtype(dtype):
Expand Down
39 changes: 30 additions & 9 deletions pandas/tests/indexes/period/test_constructors.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,11 @@

import pandas as pd
from pandas import Index, Period, PeriodIndex, Series, date_range, offsets, period_range
import pandas.core.indexes.period as period
from pandas.core.arrays import PeriodArray
import pandas.util.testing as tm


class TestPeriodIndex:
def setup_method(self, method):
pass

def test_construction_base_constructor(self):
# GH 13664
arr = [pd.Period("2011-01", freq="M"), pd.NaT, pd.Period("2011-03", freq="M")]
Expand All @@ -32,6 +29,30 @@ def test_construction_base_constructor(self):
pd.Index(np.array(arr)), pd.Index(np.array(arr), dtype=object)
)

def test_base_constructor_with_period_dtype(self):
dtype = PeriodDtype("D")
values = ["2011-01-01", "2012-03-04", "2014-05-01"]
result = pd.Index(values, dtype=dtype)

expected = pd.PeriodIndex(values, dtype=dtype)
tm.assert_index_equal(result, expected)

@pytest.mark.parametrize(
"values_constructor", [list, np.array, PeriodIndex, PeriodArray._from_sequence]
)
def test_index_object_dtype(self, values_constructor):
# Index(periods, dtype=object) is an Index (not an PeriodIndex)
periods = [
pd.Period("2011-01", freq="M"),
pd.NaT,
pd.Period("2011-03", freq="M"),
]
values = values_constructor(periods)
result = Index(values, dtype=object)

assert type(result) is Index
tm.assert_numpy_array_equal(result.values, np.array(values))

def test_constructor_use_start_freq(self):
# GH #1118
p = Period("4/2/2012", freq="B")
Expand Down Expand Up @@ -201,7 +222,7 @@ def test_constructor_dtype(self):
assert res.dtype == "period[M]"

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

def test_constructor_empty(self):
Expand Down Expand Up @@ -261,25 +282,25 @@ def test_constructor_pi_nat(self):
def test_constructor_incompat_freq(self):
msg = "Input has different freq=D from PeriodIndex\\(freq=M\\)"

with pytest.raises(period.IncompatibleFrequency, match=msg):
with pytest.raises(IncompatibleFrequency, match=msg):
PeriodIndex(
[Period("2011-01", freq="M"), pd.NaT, Period("2011-01", freq="D")]
)

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

# first element is pd.NaT
with pytest.raises(period.IncompatibleFrequency, match=msg):
with pytest.raises(IncompatibleFrequency, match=msg):
PeriodIndex(
[pd.NaT, Period("2011-01", freq="M"), Period("2011-01", freq="D")]
)

with pytest.raises(period.IncompatibleFrequency, match=msg):
with pytest.raises(IncompatibleFrequency, match=msg):
PeriodIndex(
np.array(
[pd.NaT, Period("2011-01", freq="M"), Period("2011-01", freq="D")]
Expand Down

0 comments on commit 09e4b78

Please sign in to comment.