Skip to content

Commit 71e6166

Browse files
authored
BUG: Fix bug in reindexing of period columns after unstack (#61114)
1 parent 66884fd commit 71e6166

File tree

4 files changed

+34
-5
lines changed

4 files changed

+34
-5
lines changed

doc/source/whatsnew/v3.0.0.rst

+1
Original file line numberDiff line numberDiff line change
@@ -703,6 +703,7 @@ Indexing
703703
- Bug in :meth:`Index.get_indexer` and similar methods when ``NaN`` is located at or after position 128 (:issue:`58924`)
704704
- Bug in :meth:`MultiIndex.insert` when a new value inserted to a datetime-like level gets cast to ``NaT`` and fails indexing (:issue:`60388`)
705705
- Bug in printing :attr:`Index.names` and :attr:`MultiIndex.levels` would not escape single quotes (:issue:`60190`)
706+
- Bug in reindexing of :class:`DataFrame` with :class:`PeriodDtype` columns in case of consolidated block (:issue:`60980`, :issue:`60273`)
706707

707708
Missing
708709
^^^^^^^

pandas/core/internals/blocks.py

+2-5
Original file line numberDiff line numberDiff line change
@@ -155,12 +155,9 @@ class Block(PandasObject, libinternals.Block):
155155
def _validate_ndim(self) -> bool:
156156
"""
157157
We validate dimension for blocks that can hold 2D values, which for now
158-
means numpy dtypes or DatetimeTZDtype.
158+
means numpy dtypes or EA dtypes like DatetimeTZDtype and PeriodDtype.
159159
"""
160-
dtype = self.dtype
161-
return not isinstance(dtype, ExtensionDtype) or isinstance(
162-
dtype, DatetimeTZDtype
163-
)
160+
return not is_1d_only_ea_dtype(self.dtype)
164161

165162
@final
166163
@cache_readonly

pandas/tests/indexing/test_indexing.py

+21
Original file line numberDiff line numberDiff line change
@@ -763,6 +763,27 @@ def test_partial_boolean_frame_indexing(self):
763763
)
764764
tm.assert_frame_equal(result, expected)
765765

766+
def test_period_column_slicing(self):
767+
# GH#60273 The transpose operation creates a single 5x1 block of PeriodDtype
768+
# Make sure it is reindexed correctly
769+
df = DataFrame(
770+
pd.period_range("2021-01-01", periods=5, freq="D"),
771+
columns=["A"],
772+
).T
773+
result = df[[0, 1, 2]]
774+
expected = DataFrame(
775+
[
776+
[
777+
pd.Period("2021-01-01", freq="D"),
778+
pd.Period("2021-01-02", freq="D"),
779+
pd.Period("2021-01-03", freq="D"),
780+
]
781+
],
782+
index=["A"],
783+
columns=[0, 1, 2],
784+
)
785+
tm.assert_frame_equal(result, expected)
786+
766787
def test_no_reference_cycle(self):
767788
df = DataFrame({"a": [0, 1], "b": [2, 3]})
768789
for name in ("loc", "iloc", "at", "iat"):

pandas/tests/internals/test_internals.py

+10
Original file line numberDiff line numberDiff line change
@@ -1320,6 +1320,16 @@ def test_period_can_hold_element(self, element):
13201320
with pytest.raises(TypeError, match="Invalid value"):
13211321
self.check_series_setitem(elem, pi, False)
13221322

1323+
def test_period_reindex_axis(self):
1324+
# GH#60273 Test reindexing of block with PeriodDtype
1325+
pi = period_range("2020", periods=5, freq="Y")
1326+
blk = new_block(pi._data.reshape(5, 1), BlockPlacement(slice(5)), ndim=2)
1327+
mgr = BlockManager(blocks=(blk,), axes=[Index(np.arange(5)), Index(["a"])])
1328+
reindexed = mgr.reindex_axis(Index([0, 2, 4]), axis=0)
1329+
result = DataFrame._from_mgr(reindexed, axes=reindexed.axes)
1330+
expected = DataFrame([[pi[0], pi[2], pi[4]]], columns=[0, 2, 4], index=["a"])
1331+
tm.assert_frame_equal(result, expected)
1332+
13231333
def check_can_hold_element(self, obj, elem, inplace: bool):
13241334
blk = obj._mgr.blocks[0]
13251335
if inplace:

0 commit comments

Comments
 (0)