Skip to content

Commit e6a4169

Browse files
Backport PR #42787: BUG: 1D slices over extension types turn into N-dimensional slices over ExtensionArrays (#42850)
Co-authored-by: Fred Reiss <[email protected]>
1 parent df83043 commit e6a4169

File tree

3 files changed

+31
-1
lines changed

3 files changed

+31
-1
lines changed

doc/source/whatsnew/v1.3.2.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ Fixed regressions
3030

3131
Bug fixes
3232
~~~~~~~~~
33-
-
33+
- 1D slices over extension types turn into N-dimensional slices over ExtensionArrays (:issue:`42430`)
3434
-
3535

3636
.. ---------------------------------------------------------------------------

pandas/core/internals/blocks.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1557,6 +1557,16 @@ def _slice(self, slicer):
15571557

15581558
return self.values[slicer]
15591559

1560+
@final
1561+
def getitem_block_index(self, slicer: slice) -> ExtensionBlock:
1562+
"""
1563+
Perform __getitem__-like specialized to slicing along index.
1564+
"""
1565+
# GH#42787 in principle this is equivalent to values[..., slicer], but we don't
1566+
# require subclasses of ExtensionArray to support that form (for now).
1567+
new_values = self.values[slicer]
1568+
return type(self)(new_values, self._mgr_locs, ndim=self.ndim)
1569+
15601570
def fillna(
15611571
self, value, limit=None, inplace: bool = False, downcast=None
15621572
) -> list[Block]:

pandas/tests/extension/base/getitem.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -425,3 +425,23 @@ def test_item(self, data):
425425

426426
with pytest.raises(ValueError, match=msg):
427427
s.item()
428+
429+
def test_ellipsis_index(self):
430+
# GH42430 1D slices over extension types turn into N-dimensional slices over
431+
# ExtensionArrays
432+
class CapturingStringArray(pd.arrays.StringArray):
433+
"""Extend StringArray to capture arguments to __getitem__"""
434+
435+
def __getitem__(self, item):
436+
self.last_item_arg = item
437+
return super().__getitem__(item)
438+
439+
df = pd.DataFrame(
440+
{"col1": CapturingStringArray(np.array(["hello", "world"], dtype=object))}
441+
)
442+
_ = df.iloc[:1]
443+
444+
# String comparison because there's no native way to compare slices.
445+
# Before the fix for GH42430, last_item_arg would get set to the 2D slice
446+
# (Ellipsis, slice(None, 1, None))
447+
self.assert_equal(str(df["col1"].array.last_item_arg), "slice(None, 1, None)")

0 commit comments

Comments
 (0)