Skip to content

Commit

Permalink
Backport PR #48246 on branch 1.4.x (REGR: iloc not possible for spars…
Browse files Browse the repository at this point in the history
…e DataFrame) (#48310)

Backport PR #48246: REGR: iloc not possible for sparse DataFrame
  • Loading branch information
simonjayhawkins committed Aug 30, 2022
1 parent bc82815 commit b537eab
Show file tree
Hide file tree
Showing 3 changed files with 24 additions and 3 deletions.
2 changes: 1 addition & 1 deletion doc/source/whatsnew/v1.4.4.rst
Expand Up @@ -33,7 +33,7 @@ Fixed regressions
- Fixed regression in :meth:`DatetimeIndex.intersection` when the :class:`DatetimeIndex` has dates crossing daylight savings time (:issue:`46702`)
- Fixed regression in :func:`merge` throwing an error when passing a :class:`Series` with a multi-level name (:issue:`47946`)
- Fixed regression in :meth:`DataFrame.eval` creating a copy when updating inplace (:issue:`47449`)
-
- Fixed regression where getting a row using :meth:`DataFrame.iloc` with :class:`SparseDtype` would raise (:issue:`46406`)

.. ---------------------------------------------------------------------------
Expand Down
17 changes: 15 additions & 2 deletions pandas/core/internals/managers.py
Expand Up @@ -995,11 +995,20 @@ def fast_xs(self, loc: int) -> ArrayLike:
dtype = interleaved_dtype([blk.dtype for blk in self.blocks])

n = len(self)
if isinstance(dtype, ExtensionDtype):

# GH#46406
immutable_ea = isinstance(dtype, SparseDtype)

if isinstance(dtype, ExtensionDtype) and not immutable_ea:
cls = dtype.construct_array_type()
result = cls._empty((n,), dtype=dtype)
else:
result = np.empty(n, dtype=dtype)
# error: Argument "dtype" to "empty" has incompatible type
# "Union[Type[object], dtype[Any], ExtensionDtype, None]"; expected
# "None"
result = np.empty(
n, dtype=object if immutable_ea else dtype # type: ignore[arg-type]
)
result = ensure_wrapped_if_datetimelike(result)

for blk in self.blocks:
Expand All @@ -1008,6 +1017,10 @@ def fast_xs(self, loc: int) -> ArrayLike:
for i, rl in enumerate(blk.mgr_locs):
result[rl] = blk.iget((i, loc))

if immutable_ea:
dtype = cast(ExtensionDtype, dtype)
result = dtype.construct_array_type()._from_sequence(result, dtype=dtype)

return result

def iget(self, i: int) -> SingleBlockManager:
Expand Down
8 changes: 8 additions & 0 deletions pandas/tests/indexing/test_loc.py
Expand Up @@ -1291,6 +1291,14 @@ def test_loc_getitem_sparse_series(self):
expected = Series([1.0, 0.0], dtype=SparseDtype("float64", 0.0))
tm.assert_series_equal(result, expected)

@pytest.mark.parametrize("indexer", ["loc", "iloc"])
def test_getitem_single_row_sparse_df(self, indexer):
# GH#46406
df = DataFrame([[1.0, 0.0, 1.5], [0.0, 2.0, 0.0]], dtype=SparseDtype(float))
result = getattr(df, indexer)[0]
expected = Series([1.0, 0.0, 1.5], dtype=SparseDtype(float), name=0)
tm.assert_series_equal(result, expected)

@pytest.mark.parametrize("key_type", [iter, np.array, Series, Index])
def test_loc_getitem_iterable(self, float_frame, key_type):
idx = key_type(["A", "B", "C"])
Expand Down

0 comments on commit b537eab

Please sign in to comment.