Skip to content

Commit 52a1725

Browse files
authored
BUG: IntervalArray.astype(categorical_dtype) losing ordered (pandas-dev#37984)
* BUG: IntervalArray.astype(categorical_dtype) losing ordered * whatsnew
1 parent 0823ed4 commit 52a1725

File tree

5 files changed

+33
-5
lines changed

5 files changed

+33
-5
lines changed

doc/source/whatsnew/v1.2.0.rst

+1
Original file line numberDiff line numberDiff line change
@@ -594,6 +594,7 @@ Interval
594594
- Bug in :meth:`DataFrame.replace` and :meth:`Series.replace` where :class:`Interval` dtypes would be converted to object dtypes (:issue:`34871`)
595595
- Bug in :meth:`IntervalIndex.take` with negative indices and ``fill_value=None`` (:issue:`37330`)
596596
- Bug in :meth:`IntervalIndex.putmask` with datetime-like dtype incorrectly casting to object dtype (:issue:`37968`)
597+
- Bug in :meth:`IntervalArray.astype` incorrectly dropping dtype information with a :class:`CategoricalDtype` object (:issue:`37984`)
597598
-
598599

599600
Indexing

pandas/core/arrays/interval.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -720,7 +720,7 @@ def astype(self, dtype, copy=True):
720720
combined = _get_combined_data(new_left, new_right)
721721
return type(self)._simple_new(combined, closed=self.closed)
722722
elif is_categorical_dtype(dtype):
723-
return Categorical(np.asarray(self))
723+
return Categorical(np.asarray(self), dtype=dtype)
724724
elif isinstance(dtype, StringDtype):
725725
return dtype.construct_array_type()._from_sequence(self, copy=False)
726726

pandas/core/indexes/interval.py

+1-3
Original file line numberDiff line numberDiff line change
@@ -373,9 +373,7 @@ def __reduce__(self):
373373
def astype(self, dtype, copy: bool = True):
374374
with rewrite_exception("IntervalArray", type(self).__name__):
375375
new_values = self._values.astype(dtype, copy=copy)
376-
if is_interval_dtype(new_values.dtype):
377-
return self._shallow_copy(new_values)
378-
return Index.astype(self, dtype, copy=copy)
376+
return Index(new_values, dtype=new_values.dtype, name=self.name)
379377

380378
@property
381379
def inferred_type(self) -> str:
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
import pytest
2+
3+
from pandas import Categorical, CategoricalDtype, Index, IntervalIndex
4+
import pandas._testing as tm
5+
6+
7+
class TestAstype:
8+
@pytest.mark.parametrize("ordered", [True, False])
9+
def test_astype_categorical_retains_ordered(self, ordered):
10+
index = IntervalIndex.from_breaks(range(5))
11+
arr = index._data
12+
13+
dtype = CategoricalDtype(None, ordered=ordered)
14+
15+
expected = Categorical(list(arr), ordered=ordered)
16+
result = arr.astype(dtype)
17+
assert result.ordered is ordered
18+
tm.assert_categorical_equal(result, expected)
19+
20+
# test IntervalIndex.astype while we're at it.
21+
result = index.astype(dtype)
22+
expected = Index(expected)
23+
tm.assert_index_equal(result, expected)

pandas/tests/indexes/interval/test_astype.py

+7-1
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,13 @@ def test_subtype_integer_errors(self):
114114
# int64 -> uint64 fails with negative values
115115
index = interval_range(-10, 10)
116116
dtype = IntervalDtype("uint64")
117-
with pytest.raises(ValueError):
117+
118+
# Until we decide what the exception message _should_ be, we
119+
# assert something that it should _not_ be.
120+
# We should _not_ be getting a message suggesting that the -10
121+
# has been wrapped around to a large-positive integer
122+
msg = "^(?!(left side of interval must be <= right side))"
123+
with pytest.raises(ValueError, match=msg):
118124
index.astype(dtype)
119125

120126

0 commit comments

Comments
 (0)