Skip to content

Commit bf072b0

Browse files
committed
BUG: frame.loc[2:, 'z'] not setting inplace when multi-block
1 parent 0ecc2c7 commit bf072b0

File tree

3 files changed

+39
-14
lines changed

3 files changed

+39
-14
lines changed

pandas/core/indexing.py

+13-4
Original file line numberDiff line numberDiff line change
@@ -1859,10 +1859,19 @@ def _setitem_single_column(self, loc: int, value, plane_indexer):
18591859
# in case of slice
18601860
ser = value[pi]
18611861
else:
1862-
# set the item, possibly having a dtype change
1863-
ser = ser.copy()
1864-
ser._mgr = ser._mgr.setitem(indexer=(pi,), value=value)
1865-
ser._maybe_update_cacher(clear=True, inplace=True)
1862+
# set the item, first attempting to operate inplace, then
1863+
# falling back to casting if necessary; see
1864+
# _whatsnew_130.notable_bug_fixes.setitem_column_try_inplace
1865+
1866+
orig_values = ser._values
1867+
ser._mgr = ser._mgr.setitem((pi,), value)
1868+
1869+
if ser._values is orig_values:
1870+
# The setitem happened inplace, so the DataFrame's values
1871+
# were modified inplace.
1872+
return
1873+
self.obj._iset_item(loc, ser, inplace=True)
1874+
return
18661875

18671876
# reset the sliced object if unique
18681877
self.obj._iset_item(loc, ser, inplace=True)

pandas/io/stata.py

+4-3
Original file line numberDiff line numberDiff line change
@@ -600,6 +600,8 @@ def _cast_to_stata_types(data: DataFrame) -> DataFrame:
600600
# Cast from unsupported types to supported types
601601
is_nullable_int = isinstance(data[col].dtype, (_IntegerDtype, BooleanDtype))
602602
orig = data[col]
603+
# We need to find orig_missing before altering data below
604+
orig_missing = orig.isna()
603605
if is_nullable_int:
604606
missing_loc = data[col].isna()
605607
if missing_loc.any():
@@ -650,11 +652,10 @@ def _cast_to_stata_types(data: DataFrame) -> DataFrame:
650652
f"supported by Stata ({float64_max})"
651653
)
652654
if is_nullable_int:
653-
missing = orig.isna()
654-
if missing.any():
655+
if orig_missing.any():
655656
# Replace missing by Stata sentinel value
656657
sentinel = StataMissingValue.BASE_MISSING_VALUES[data[col].dtype.name]
657-
data.loc[missing, col] = sentinel
658+
data.loc[orig_missing, col] = sentinel
658659
if ws:
659660
warnings.warn(ws, PossiblePrecisionLoss)
660661

pandas/tests/frame/indexing/test_setitem.py

+22-7
Original file line numberDiff line numberDiff line change
@@ -995,22 +995,37 @@ def test_setitem_always_copy(self, float_frame):
995995
float_frame["E"][5:10] = np.nan
996996
assert notna(s[5:10]).all()
997997

998-
def test_setitem_clear_caches(self):
999-
# see GH#304
998+
@pytest.mark.parametrize("consolidate", [True, False])
999+
def test_setitem_partial_column_inplace(self, consolidate, using_array_manager):
1000+
# This setting should be in-place, regardless of whether frame is
1001+
# single-block or multi-block
1002+
# GH#304 this used to be incorrectly not-inplace, in which case
1003+
# we needed to ensure _item_cache was cleared.
1004+
10001005
df = DataFrame(
10011006
{"x": [1.1, 2.1, 3.1, 4.1], "y": [5.1, 6.1, 7.1, 8.1]}, index=[0, 1, 2, 3]
10021007
)
10031008
df.insert(2, "z", np.nan)
1009+
if not using_array_manager:
1010+
if consolidate:
1011+
df._consolidate_inplace()
1012+
assert len(df._mgr.blocks) == 1
1013+
else:
1014+
assert len(df._mgr.blocks) == 2
10041015

1005-
# cache it
1006-
foo = df["z"]
1007-
df.loc[df.index[2:], "z"] = 42
1016+
zvals = df["z"]._values
10081017

1009-
expected = Series([np.nan, np.nan, 42, 42], index=df.index, name="z")
1018+
df.loc[2:, "z"] = 42
10101019

1011-
assert df["z"] is not foo
1020+
expected = Series([np.nan, np.nan, 42, 42], index=df.index, name="z")
10121021
tm.assert_series_equal(df["z"], expected)
10131022

1023+
# check setting occurred in-place
1024+
tm.assert_numpy_array_equal(zvals, expected.values)
1025+
assert np.shares_memory(zvals, df["z"]._values)
1026+
if not consolidate:
1027+
assert df["z"]._values is zvals
1028+
10141029
def test_setitem_duplicate_columns_not_inplace(self):
10151030
# GH#39510
10161031
cols = ["A", "B"] * 2

0 commit comments

Comments
 (0)