Skip to content

Commit 776857a

Browse files
authored
BUG: Fix bug in loc setitem changing the dtype when condition is False (#37672)
1 parent 6283499 commit 776857a

File tree

3 files changed

+30
-0
lines changed

3 files changed

+30
-0
lines changed

doc/source/whatsnew/v1.4.0.rst

+1
Original file line numberDiff line numberDiff line change
@@ -699,6 +699,7 @@ Indexing
699699
- Bug in :meth:`DataFrame.loc.__getitem__` incorrectly raising ``KeyError`` when selecting a single column with a boolean key (:issue:`44322`).
700700
- Bug in setting :meth:`DataFrame.iloc` with a single ``ExtensionDtype`` column and setting 2D values e.g. ``df.iloc[:] = df.values`` incorrectly raising (:issue:`44514`)
701701
- Bug in indexing on columns with ``loc`` or ``iloc`` using a slice with a negative step with ``ExtensionDtype`` columns incorrectly raising (:issue:`44551`)
702+
- Bug in :meth:`DataFrame.loc.__setitem__` changing dtype when indexer was completely ``False`` (:issue:`37550`)
702703
- Bug in :meth:`IntervalIndex.get_indexer_non_unique` returning boolean mask instead of array of integers for a non unique and non monotonic index (:issue:`44084`)
703704
- Bug in :meth:`IntervalIndex.get_indexer_non_unique` not handling targets of ``dtype`` 'object' with NaNs correctly (:issue:`44482`)
704705
-

pandas/core/indexing.py

+2
Original file line numberDiff line numberDiff line change
@@ -2058,6 +2058,8 @@ def ravel(i):
20582058
# we have a frame, with multiple indexers on both axes; and a
20592059
# series, so need to broadcast (see GH5206)
20602060
if sum_aligners == self.ndim and all(is_sequence(_) for _ in indexer):
2061+
if is_empty_indexer(indexer[0], ser._values):
2062+
return ser._values.copy()
20612063
ser = ser.reindex(obj.axes[0][indexer[0]], copy=True)._values
20622064

20632065
# single indexer

pandas/tests/frame/indexing/test_setitem.py

+27
Original file line numberDiff line numberDiff line change
@@ -922,6 +922,33 @@ def test_setitem_boolean_mask(self, mask_type, float_frame):
922922
expected.values[np.array(mask)] = np.nan
923923
tm.assert_frame_equal(result, expected)
924924

925+
@pytest.mark.xfail(reason="Currently empty indexers are treated as all False")
926+
@pytest.mark.parametrize("box", [list, np.array, Series])
927+
def test_setitem_loc_empty_indexer_raises_with_non_empty_value(self, box):
928+
# GH#37672
929+
df = DataFrame({"a": ["a"], "b": [1], "c": [1]})
930+
if box == Series:
931+
indexer = box([], dtype="object")
932+
else:
933+
indexer = box([])
934+
msg = "Must have equal len keys and value when setting with an iterable"
935+
with pytest.raises(ValueError, match=msg):
936+
df.loc[indexer, ["b"]] = [1]
937+
938+
@pytest.mark.parametrize("box", [list, np.array, Series])
939+
def test_setitem_loc_only_false_indexer_dtype_changed(self, box):
940+
# GH#37550
941+
# Dtype is only changed when value to set is a Series and indexer is
942+
# empty/bool all False
943+
df = DataFrame({"a": ["a"], "b": [1], "c": [1]})
944+
indexer = box([False])
945+
df.loc[indexer, ["b"]] = 10 - df["c"]
946+
expected = DataFrame({"a": ["a"], "b": [1], "c": [1]})
947+
tm.assert_frame_equal(df, expected)
948+
949+
df.loc[indexer, ["b"]] = 9
950+
tm.assert_frame_equal(df, expected)
951+
925952
@pytest.mark.parametrize("indexer", [tm.setitem, tm.loc])
926953
def test_setitem_boolean_mask_aligning(self, indexer):
927954
# GH#39931

0 commit comments

Comments
 (0)