Skip to content

Commit 84b3f91

Browse files
authored
BUG: Series.__delitem__ converting EAs to ndarrays (pandas-dev#40763)
1 parent 986c5ec commit 84b3f91

File tree

3 files changed

+45
-15
lines changed

3 files changed

+45
-15
lines changed

doc/source/whatsnew/v1.3.0.rst

+1
Original file line numberDiff line numberDiff line change
@@ -642,6 +642,7 @@ Indexing
642642
- Bug in setting ``numpy.timedelta64`` values into an object-dtype :class:`Series` using a boolean indexer (:issue:`39488`)
643643
- Bug in setting numeric values into a into a boolean-dtypes :class:`Series` using ``at`` or ``iat`` failing to cast to object-dtype (:issue:`39582`)
644644
- Bug in :meth:`DataFrame.loc.__setitem__` when setting-with-expansion incorrectly raising when the index in the expanding axis contains duplicates (:issue:`40096`)
645+
- Bug in :meth:`Series.__delitem__` with ``ExtensionDtype`` incorrectly casting to ``ndarray`` (:issue:`40386`)
645646

646647
Missing
647648
^^^^^^^

pandas/core/internals/blocks.py

+23-15
Original file line numberDiff line numberDiff line change
@@ -1338,7 +1338,28 @@ def quantile(
13381338
return new_block(result, placement=self._mgr_locs, ndim=2)
13391339

13401340

1341-
class ExtensionBlock(Block):
1341+
class EABackedBlock(Block):
1342+
"""
1343+
Mixin for Block subclasses backed by ExtensionArray.
1344+
"""
1345+
1346+
values: ExtensionArray
1347+
1348+
def delete(self, loc) -> None:
1349+
"""
1350+
Delete given loc(-s) from block in-place.
1351+
"""
1352+
# This will be unnecessary if/when __array_function__ is implemented
1353+
self.values = self.values.delete(loc)
1354+
self.mgr_locs = self._mgr_locs.delete(loc)
1355+
try:
1356+
self._cache.clear()
1357+
except AttributeError:
1358+
# _cache not yet initialized
1359+
pass
1360+
1361+
1362+
class ExtensionBlock(EABackedBlock):
13421363
"""
13431364
Block for holding extension types.
13441365
@@ -1647,7 +1668,7 @@ class NumericBlock(Block):
16471668
is_numeric = True
16481669

16491670

1650-
class NDArrayBackedExtensionBlock(Block):
1671+
class NDArrayBackedExtensionBlock(EABackedBlock):
16511672
"""
16521673
Block backed by an NDArrayBackedExtensionArray
16531674
"""
@@ -1754,19 +1775,6 @@ def fillna(
17541775
new_values = values.fillna(value=value, limit=limit)
17551776
return [self.make_block_same_class(values=new_values)]
17561777

1757-
def delete(self, loc) -> None:
1758-
"""
1759-
Delete given loc(-s) from block in-place.
1760-
"""
1761-
# This will be unnecessary if/when __array_function__ is implemented
1762-
self.values = self.values.delete(loc, axis=0)
1763-
self.mgr_locs = self._mgr_locs.delete(loc)
1764-
try:
1765-
self._cache.clear()
1766-
except AttributeError:
1767-
# _cache not yet initialized
1768-
pass
1769-
17701778

17711779
class DatetimeLikeBlock(NDArrayBackedExtensionBlock):
17721780
"""Mixin class for DatetimeLikeBlock, DatetimeTZBlock."""

pandas/tests/series/indexing/test_delitem.py

+21
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
from pandas import (
44
Index,
55
Series,
6+
date_range,
67
)
78
import pandas._testing as tm
89

@@ -50,3 +51,23 @@ def test_delitem_missing_key(self):
5051

5152
with pytest.raises(KeyError, match=r"^0$"):
5253
del s[0]
54+
55+
def test_delitem_extension_dtype(self):
56+
# GH#40386
57+
# DatetimeTZDtype
58+
dti = date_range("2016-01-01", periods=3, tz="US/Pacific")
59+
ser = Series(dti)
60+
61+
expected = ser[[0, 2]]
62+
del ser[1]
63+
assert ser.dtype == dti.dtype
64+
tm.assert_series_equal(ser, expected)
65+
66+
# PeriodDtype
67+
pi = dti.tz_localize(None).to_period("D")
68+
ser = Series(pi)
69+
70+
expected = ser[:2]
71+
del ser[2]
72+
assert ser.dtype == pi.dtype
73+
tm.assert_series_equal(ser, expected)

0 commit comments

Comments
 (0)