Skip to content

Commit 4f7da2c

Browse files
authored
BUG: loc casting to float for scalar with MultiIndex df (#41374)
1 parent e4d0c1d commit 4f7da2c

File tree

3 files changed

+20
-10
lines changed

3 files changed

+20
-10
lines changed

doc/source/whatsnew/v1.3.0.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -874,6 +874,7 @@ Indexing
874874
- Bug in :meth:`DataFrame.__setitem__` and :meth:`DataFrame.iloc.__setitem__` raising ``ValueError`` when trying to index with a row-slice and setting a list as values (:issue:`40440`)
875875
- Bug in :meth:`DataFrame.loc` not raising ``KeyError`` when key was not found in :class:`MultiIndex` when levels contain more values than used (:issue:`41170`)
876876
- Bug in :meth:`DataFrame.loc.__setitem__` when setting-with-expansion incorrectly raising when the index in the expanding axis contains duplicates (:issue:`40096`)
877+
- Bug in :meth:`DataFrame.loc.__getitem__` with :class:`MultiIndex` casting to float when at least one column is from has float dtype and we retrieve a scalar (:issue:`41369`)
877878
- Bug in :meth:`DataFrame.loc` incorrectly matching non-boolean index elements (:issue:`20432`)
878879
- Bug in :meth:`Series.__delitem__` with ``ExtensionDtype`` incorrectly casting to ``ndarray`` (:issue:`40386`)
879880
- Bug in :meth:`DataFrame.__setitem__` raising ``TypeError`` when using a str subclass as the column name with a :class:`DatetimeIndex` (:issue:`37366`)

pandas/core/indexing.py

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -886,26 +886,22 @@ def _getitem_nested_tuple(self, tup: tuple):
886886
# handle the multi-axis by taking sections and reducing
887887
# this is iterative
888888
obj = self.obj
889-
axis = 0
890-
for key in tup:
889+
# GH#41369 Loop in reverse order ensures indexing along columns before rows
890+
# which selects only necessary blocks which avoids dtype conversion if possible
891+
axis = len(tup) - 1
892+
for key in tup[::-1]:
891893

892894
if com.is_null_slice(key):
893-
axis += 1
895+
axis -= 1
894896
continue
895897

896-
current_ndim = obj.ndim
897898
obj = getattr(obj, self.name)._getitem_axis(key, axis=axis)
898-
axis += 1
899+
axis -= 1
899900

900901
# if we have a scalar, we are done
901902
if is_scalar(obj) or not hasattr(obj, "ndim"):
902903
break
903904

904-
# has the dim of the obj changed?
905-
# GH 7199
906-
if obj.ndim < current_ndim:
907-
axis -= 1
908-
909905
return obj
910906

911907
def _convert_to_indexer(self, key, axis: int, is_setter: bool = False):

pandas/tests/indexing/multiindex/test_loc.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -831,3 +831,16 @@ def test_mi_add_cell_missing_row_non_unique():
831831
columns=MultiIndex.from_product([[1, 2], ["A", "B"]]),
832832
)
833833
tm.assert_frame_equal(result, expected)
834+
835+
836+
def test_loc_get_scalar_casting_to_float():
837+
# GH#41369
838+
df = DataFrame(
839+
{"a": 1.0, "b": 2}, index=MultiIndex.from_arrays([[3], [4]], names=["c", "d"])
840+
)
841+
result = df.loc[(3, 4), "b"]
842+
assert result == 2
843+
assert isinstance(result, np.int64)
844+
result = df.loc[[(3, 4)], "b"].iloc[0]
845+
assert result == 2
846+
assert isinstance(result, np.int64)

0 commit comments

Comments
 (0)