Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

BUG: df[col] = arr should not overwrite data in df[col] #35417

Closed
wants to merge 150 commits into from
Closed
Show file tree
Hide file tree
Changes from 65 commits
Commits
Show all changes
150 commits
Select commit Hold shift + click to select a range
a1ce4fc
Make df[col] insert a new array, never overwrite
jbrockmendel Jul 26, 2020
b1913b7
Merge branch 'master' of https://github.com/pandas-dev/pandas into 33457
jbrockmendel Jul 26, 2020
e600237
whatsnew
TomAugspurger Jul 27, 2020
140f5f2
update tests
jbrockmendel Jul 28, 2020
c096c5d
Merge branch 'master' of https://github.com/pandas-dev/pandas into 33457
jbrockmendel Jul 28, 2020
cbd45e8
Merge branch 'master' of https://github.com/pandas-dev/pandas into 33457
jbrockmendel Jul 30, 2020
989ba97
update whatsnew
jbrockmendel Jul 30, 2020
bf6e5f5
Merge branch 'master' of https://github.com/pandas-dev/pandas into 33457
jbrockmendel Aug 5, 2020
a5ffd10
Merge branch 'master' of https://github.com/pandas-dev/pandas into 33457
jbrockmendel Aug 8, 2020
e126ab5
Merge branch 'master' of https://github.com/pandas-dev/pandas into 33457
jbrockmendel Aug 12, 2020
8c4f9f3
Merge branch 'master' of https://github.com/pandas-dev/pandas into 33457
jbrockmendel Aug 13, 2020
f716904
Merge branch 'master' of https://github.com/pandas-dev/pandas into 33457
jbrockmendel Aug 15, 2020
59e447a
Update merge test
jbrockmendel Aug 15, 2020
09e89ee
Merge branch 'master' of https://github.com/pandas-dev/pandas into 33457
jbrockmendel Aug 18, 2020
11b8093
Fix cython groubpy.apply func for funcs that mutate inplace
jbrockmendel Aug 18, 2020
4271303
cleanup commented-out
jbrockmendel Aug 18, 2020
ed0af51
mypy fixup
jbrockmendel Aug 18, 2020
dffae7e
Merge branch 'master' of https://github.com/pandas-dev/pandas into 33457
jbrockmendel Aug 26, 2020
a7f363b
Merge branch 'master' of https://github.com/pandas-dev/pandas into 33457
jbrockmendel Aug 27, 2020
53992df
Test for #35731
jbrockmendel Aug 27, 2020
0a133d7
Merge branch 'master' of https://github.com/pandas-dev/pandas into 33457
jbrockmendel Aug 31, 2020
db1b668
Merge branch 'master' of https://github.com/pandas-dev/pandas into 33457
jbrockmendel Sep 2, 2020
858d6cb
Merge branch 'master' of https://github.com/pandas-dev/pandas into 33457
jbrockmendel Sep 7, 2020
3deb0a7
Merge branch 'master' of https://github.com/pandas-dev/pandas into 33457
jbrockmendel Sep 14, 2020
68e8715
Merge branch 'master' of https://github.com/pandas-dev/pandas into 33457
jbrockmendel Sep 14, 2020
3a74222
Merge branch 'master' of https://github.com/pandas-dev/pandas into 33457
jbrockmendel Sep 22, 2020
b0896be
Merge branch 'master' of https://github.com/pandas-dev/pandas into 33457
jbrockmendel Sep 22, 2020
f9498a3
revert accidental
jbrockmendel Oct 11, 2020
d81a696
Merge branch 'master' of https://github.com/pandas-dev/pandas into 33457
jbrockmendel Oct 11, 2020
33ef890
Merge branch 'master' of https://github.com/pandas-dev/pandas into 33457
jbrockmendel Oct 12, 2020
ea49ae2
move whatsnew note
jbrockmendel Oct 12, 2020
1a850c8
Merge branch 'master' of https://github.com/pandas-dev/pandas into 33457
jbrockmendel Oct 12, 2020
fed4782
update version ref
jbrockmendel Oct 12, 2020
0633cc6
Merge branch 'master' of https://github.com/pandas-dev/pandas into 33457
jbrockmendel Oct 13, 2020
a00702a
restore
jbrockmendel Oct 13, 2020
1dd58ab
split_path compat
jbrockmendel Oct 14, 2020
4ffe7f4
Merge branch 'master' of https://github.com/pandas-dev/pandas into 33457
jbrockmendel Oct 16, 2020
247d0f8
Merge branch 'master' of https://github.com/pandas-dev/pandas into 33457
jbrockmendel Oct 16, 2020
9164c83
Merge branch 'master' of https://github.com/pandas-dev/pandas into 33457
jbrockmendel Oct 22, 2020
080c7e9
Merge branch 'master' of https://github.com/pandas-dev/pandas into 33457
jbrockmendel Oct 22, 2020
b47ed01
Merge branch 'master' of https://github.com/pandas-dev/pandas into 33457
jbrockmendel Oct 23, 2020
0290975
Merge branch 'master' of https://github.com/pandas-dev/pandas into 33457
jbrockmendel Oct 23, 2020
13b683d
Merge branch 'master' of https://github.com/pandas-dev/pandas into 33457
jbrockmendel Oct 23, 2020
7e9ea2d
lint fixup
jbrockmendel Oct 23, 2020
bd55d67
Merge branch 'master' of https://github.com/pandas-dev/pandas into 33457
jbrockmendel Oct 25, 2020
ae9c707
Merge branch 'master' of https://github.com/pandas-dev/pandas into 33457
jbrockmendel Oct 26, 2020
4dd24ca
Merge branch 'master' of https://github.com/pandas-dev/pandas into 33457
jbrockmendel Oct 26, 2020
253f625
Merge branch 'master' of https://github.com/pandas-dev/pandas into 33457
jbrockmendel Oct 31, 2020
0b28fc0
Merge branch 'master' of https://github.com/pandas-dev/pandas into 33457
jbrockmendel Nov 2, 2020
9c5e6fa
Merge branch 'master' of https://github.com/pandas-dev/pandas into 33457
jbrockmendel Nov 17, 2020
2e0bf61
Merge branch 'master' of https://github.com/pandas-dev/pandas into 33457
jbrockmendel Nov 23, 2020
04af8fa
doc fixup, split tests
jbrockmendel Nov 23, 2020
1d2b6d7
update test expected
jbrockmendel Nov 23, 2020
65d466b
Merge branch 'master' of https://github.com/pandas-dev/pandas into 33457
jbrockmendel Nov 25, 2020
13077e9
Merge branch 'master' of https://github.com/pandas-dev/pandas into 33457
jbrockmendel Nov 26, 2020
f013ec3
Merge branch 'master' of https://github.com/pandas-dev/pandas into 33457
jbrockmendel Dec 3, 2020
66d5ed0
Merge branch 'master' of https://github.com/pandas-dev/pandas into 33457
jbrockmendel Dec 4, 2020
f23245b
Merge branch 'master' of https://github.com/pandas-dev/pandas into 33457
jbrockmendel Dec 5, 2020
23e9462
Merge branch 'master' of https://github.com/pandas-dev/pandas into 33457
jbrockmendel Dec 6, 2020
6c8b15f
fix broken test
jbrockmendel Dec 7, 2020
03b3015
Merge branch 'master' of https://github.com/pandas-dev/pandas into 33457
jbrockmendel Dec 7, 2020
687d262
troubleshoot 32bit builds
jbrockmendel Dec 7, 2020
9164a1e
Merge branch 'master' of https://github.com/pandas-dev/pandas into 33457
jbrockmendel Dec 8, 2020
02585c5
move whatsnew
jbrockmendel Dec 8, 2020
3731fc8
restore 1.2.0 whatnsew
jbrockmendel Dec 8, 2020
184f013
Merge branch 'master' of https://github.com/pandas-dev/pandas into 33457
jbrockmendel Dec 9, 2020
8503671
troubleshoot
jbrockmendel Dec 9, 2020
34a96f7
Merge branch 'master' of https://github.com/pandas-dev/pandas into 33457
jbrockmendel Dec 10, 2020
a82f62b
Merge branch 'master' of https://github.com/pandas-dev/pandas into 33457
jbrockmendel Dec 11, 2020
fe58441
troubleshoot
jbrockmendel Dec 11, 2020
28e6296
Merge branch 'master' of https://github.com/pandas-dev/pandas into 33457
jbrockmendel Dec 13, 2020
1e802b8
Merge branch 'master' of https://github.com/pandas-dev/pandas into 33457
jbrockmendel Dec 14, 2020
c1ab90f
Merge branch 'master' of https://github.com/pandas-dev/pandas into 33457
jbrockmendel Dec 28, 2020
382def7
Merge branch 'master' of https://github.com/pandas-dev/pandas into 33457
jbrockmendel Dec 30, 2020
4023a16
Merge branch 'master' of https://github.com/pandas-dev/pandas into 33457
jbrockmendel Dec 30, 2020
1e60537
flesh out tests
jbrockmendel Dec 30, 2020
072ef99
Merge branch 'master' of https://github.com/pandas-dev/pandas into 33457
jbrockmendel Jan 8, 2021
51fe3b2
Merge branch 'master' of https://github.com/pandas-dev/pandas into 33457
jbrockmendel Jan 12, 2021
7edd45a
Merge branch 'master' of https://github.com/pandas-dev/pandas into 33457
jbrockmendel Jan 16, 2021
9783bce
arraymanager mypy fixup
jbrockmendel Jan 16, 2021
df6110e
Merge branch 'master' into 33457
jbrockmendel Jan 22, 2021
d7257f2
Merge branch 'master' of https://github.com/pandas-dev/pandas into 33457
jbrockmendel Jan 25, 2021
1f9f9c3
Merge branch 'master' of https://github.com/pandas-dev/pandas into 33457
jbrockmendel Jan 27, 2021
36fb2d4
Merge branch 'master' of https://github.com/pandas-dev/pandas into 33457
jbrockmendel Jan 28, 2021
1292a92
Merge branch 'master' of https://github.com/pandas-dev/pandas into 33457
jbrockmendel Jan 29, 2021
9b127bf
Merge branch 'master' into 33457
jbrockmendel Feb 2, 2021
831dc71
Merge branch 'master' into 33457
jbrockmendel Feb 3, 2021
1d50325
Merge branch 'master' of https://github.com/pandas-dev/pandas into 33457
jbrockmendel Feb 3, 2021
d72f379
Merge branch 'master' of https://github.com/pandas-dev/pandas into 33457
jbrockmendel Feb 4, 2021
81e92d8
Merge branch 'master' into 33457
jbrockmendel Feb 11, 2021
67435f8
simplify test
jbrockmendel Feb 27, 2021
ab833aa
Merge branch 'master' into 33457
jbrockmendel Feb 27, 2021
017501e
Merge branch 'master' into 33457
jbrockmendel Mar 15, 2021
0219f7f
Merge branch 'master' into 33457
jbrockmendel Mar 15, 2021
032a55a
Merge branch 'master' into 33457
jbrockmendel Mar 17, 2021
51d102b
un-xfail
jbrockmendel Mar 17, 2021
bd6816b
Merge branch 'master' into 33457
jbrockmendel Mar 18, 2021
908b57b
Merge branch 'master' into 33457
jbrockmendel Mar 18, 2021
62f2437
32bit compat
jbrockmendel Mar 18, 2021
36b3302
troublehsoot
jbrockmendel Mar 18, 2021
37c9d22
troubleshoot 32bit builds
jbrockmendel Mar 18, 2021
0862ece
Merge branch 'master' into 33457
jbrockmendel Mar 19, 2021
38d8106
troubleshoot 32 bit
jbrockmendel Mar 19, 2021
647a393
DOC: suppress warnings from CategoricalBlock deprecation
jbrockmendel Mar 20, 2021
8b8d6a2
Merge branch 'master' into ci-doc
jbrockmendel Mar 20, 2021
9c6e008
Merge branch 'ci-doc' into 33457
jbrockmendel Mar 21, 2021
8285ece
troubleshoot 32 bit builds
jbrockmendel Mar 21, 2021
270be1e
troubleshoot 32bit builds
jbrockmendel Mar 21, 2021
9cf69c9
typo fixup
jbrockmendel Mar 21, 2021
065869a
Merge branch 'master' into 33457
jbrockmendel Mar 21, 2021
ca260c5
32bit troubleshoot
jbrockmendel Mar 21, 2021
5dcdc4a
Merge branch 'master' into 33457
jbrockmendel Mar 23, 2021
a03dcc3
Merge branch 'master' into 33457
jbrockmendel Mar 26, 2021
a1c5732
revert troubleshoot
jbrockmendel Mar 26, 2021
47b841a
Merge branch 'master' into 33457
jbrockmendel Mar 30, 2021
df060a5
Merge branch 'master' into 33457
jbrockmendel Mar 31, 2021
017b817
Merge branch 'master' into 33457
jbrockmendel Mar 31, 2021
0821a60
update test
jbrockmendel Apr 1, 2021
608fb9d
Merge branch 'master' into 33457
jbrockmendel Apr 1, 2021
a70fcc2
Merge branch 'master' into 33457
jbrockmendel Apr 5, 2021
effd630
Merge branch 'master' into 33457
jbrockmendel Apr 5, 2021
4e30881
Merge branch 'master' into 33457
jbrockmendel Apr 6, 2021
a254ed0
Merge branch 'master' into 33457
jbrockmendel Apr 8, 2021
df7b4d3
Merge branch 'master' into 33457
jbrockmendel Apr 9, 2021
8f49c7f
Merge branch 'master' into 33457
jbrockmendel Apr 11, 2021
a66afa0
revert duplicated whatsnew notes
jbrockmendel Apr 11, 2021
fb95732
revert unrelated test fix
jbrockmendel Apr 11, 2021
c0bace5
Merge branch 'master' into 33457
jbrockmendel Apr 16, 2021
9e43fe9
Merge branch 'master' into 33457
jbrockmendel Apr 16, 2021
f47fa2e
Merge branch 'master' into 33457
jbrockmendel Apr 27, 2021
29d3bba
Merge branch 'master' into 33457
jbrockmendel Apr 30, 2021
5b8de9a
Merge branch 'master' into 33457
jbrockmendel May 4, 2021
79c7ae2
Merge branch 'master' into 33457
jbrockmendel May 9, 2021
fa2dcea
Merge branch 'master' into 33457
jbrockmendel May 17, 2021
0e8f671
Merge branch 'master' into 33457
jbrockmendel Nov 8, 2021
3cdeeb4
Merge branch 'master' into 33457
jbrockmendel Nov 9, 2021
acd3514
Merge branch 'master' into 33457
jbrockmendel Nov 11, 2021
d97a1ac
Merge branch 'master' into 33457
jbrockmendel Nov 11, 2021
4342f5d
ArrayManager fixup
jbrockmendel Nov 11, 2021
f4dafc6
Merge branch 'master' into 33457
jbrockmendel Nov 12, 2021
bebb12f
avoid warning
jbrockmendel Nov 12, 2021
04475e3
Merge branch 'master' into 33457
jbrockmendel Nov 14, 2021
ed6f3ec
Merge branch 'master' into 33457
jbrockmendel Nov 26, 2021
fe9fe66
fixed on AM
jbrockmendel Nov 26, 2021
1ae50bf
Merge branch 'master' into 33457
jbrockmendel Nov 28, 2021
9d32c62
Merge branch 'master' into 33457
jbrockmendel Dec 16, 2021
8972875
Merge branch 'master' into 33457
jbrockmendel Dec 29, 2021
6524331
revert whitespace change
jbrockmendel Dec 29, 2021
123568d
revert no-longer-necessary
jbrockmendel Dec 29, 2021
8bef37a
Merge branch 'master' into 33457
jbrockmendel Dec 29, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
77 changes: 76 additions & 1 deletion doc/source/whatsnew/v1.3.0.rst
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,82 @@ Notable bug fixes

These are bug fixes that might have notable behavior changes.

Assigning with ``DataFrame.__setitem__`` consistently creates a new array
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

Assigning values with ``DataFrame.__setitem__`` now consistently assigns a new array, rather than mutating inplace (:issue:`33457`, :issue:`35271`, :issue:`35266`)

Previously, ``DataFrame.__setitem__`` would sometimes operate inplace on the
underlying array, and sometimes assign a new array. Fixing this inconsistency
can have behavior-changing implications for workloads that relied on inplace
mutation. The two most common cases are creating a ``DataFrame`` from an array
and slicing a ``DataFrame``.

*Previous Behavior*

The array would be mutated inplace for some dtypes, like NumPy's ``int64`` dtype.

.. code-block:: python

>>> import pandas as pd
>>> import numpy as np
>>> a = np.array([1, 2, 3])
>>> df = pd.DataFrame(a, columns=['a'])
>>> df['a'] = 0
>>> a # mutated inplace
array([0, 0, 0])

But not others, like :class:`Int64Dtype`.

.. code-block:: python

>>> import pandas as pd
>>> import numpy as np
>>> a = pd.array([1, 2, 3], dtype="Int64")
>>> df = pd.DataFrame(a, columns=['a'])
>>> df['a'] = 0
>>> a # not mutated
<IntegerArray>
[1, 2, 3]
Length: 3, dtype: Int64


*New Behavior*

In pandas 1.3.0, ``DataFrame.__setitem__`` consistently sets on a new array rather than
mutating the existing array inplace.

For NumPy's int64 dtype

.. ipython:: python

import pandas as pd
import numpy as np
a = np.array([1, 2, 3])
df = pd.DataFrame(a, columns=['a'])
df['a'] = 0
a # not mutated

For :class:`Int64Dtype`.

.. ipython:: python

import pandas as pd
import numpy as np
a = pd.array([1, 2, 3], dtype="Int64")
df = pd.DataFrame(a, columns=['a'])
df['a'] = 0
a # not mutated

This also affects cases where a second ``Series`` or ``DataFrame`` is a view on a first ``DataFrame``.

.. code-block:: python

df = pd.DataFrame({"A": [1, 2, 3]})
df2 = df[['A']]
df['A'] = np.array([0, 0, 0])

Previously, whether ``df2`` was mutated depending on the dtype of the array being assigned to. Now, a new array is consistently assigned, so ``df2`` is not mutated.

.. _whatsnew_130.api_breaking.deps:

Expand Down Expand Up @@ -127,7 +202,7 @@ Interval

Indexing
^^^^^^^^

- Bug in :meth:`DataFrame.iloc.__setitem__` creating a new array instead of overwriting ``Categorical`` values in-place (:issue:`35417`)
-
-

Expand Down
25 changes: 24 additions & 1 deletion pandas/_libs/reduction.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -406,7 +406,8 @@ cdef class BlockSlider:
"""
cdef:
object frame, dummy, index, block
list blk_values
list blocks, blk_values
ndarray orig_blklocs, orig_blknos
ndarray values
Slider idx_slider
char **base_ptrs
Expand All @@ -418,6 +419,13 @@ cdef class BlockSlider:
self.dummy = frame[:0]
self.index = self.dummy.index

# GH#35417 attributes we need to restore at each step in case
# the function modified them.
mgr = self.dummy._mgr
self.orig_blklocs = mgr.blklocs
self.orig_blknos = mgr.blknos
self.blocks = [x for x in self.dummy._mgr.blocks]

self.blk_values = [block.values for block in self.dummy._mgr.blocks]

for values in self.blk_values:
Expand All @@ -441,6 +449,9 @@ cdef class BlockSlider:
cdef:
ndarray arr
Py_ssize_t i

self._restore_blocks()

# move blocks
for i in range(self.nblocks):
arr = self.blk_values[i]
Expand All @@ -460,9 +471,21 @@ cdef class BlockSlider:
cdef:
ndarray arr
Py_ssize_t i

self._restore_blocks()

for i in range(self.nblocks):
arr = self.blk_values[i]

# axis=1 is the frame's axis=0
arr.data = self.base_ptrs[i]
arr.shape[1] = 0

cdef _restore_blocks(self):
"""
Ensure that we have the original blocks, blknos, and blklocs.
"""
mgr = self.dummy._mgr
mgr.blocks = self.blocks
mgr._blklocs = self.orig_blklocs
mgr._blknos = self.orig_blknos
2 changes: 2 additions & 0 deletions pandas/_testing.py
Original file line number Diff line number Diff line change
Expand Up @@ -1140,6 +1140,8 @@ def _get_base(obj):
raise AssertionError(f"{repr(left_base)} is {repr(right_base)}")

def _raise(left, right, err_msg):
__tracebackhide__ = True

if err_msg is None:
if left.shape != right.shape:
raise_assert_detail(
Expand Down
6 changes: 3 additions & 3 deletions pandas/core/frame.py
Original file line number Diff line number Diff line change
Expand Up @@ -3211,17 +3211,17 @@ def _setitem_frame(self, key, value):
self._check_setitem_copy()
self._where(-key, value, inplace=True)

def _iset_item(self, loc: int, value):
def _iset_item(self, loc: int, value, inplace: bool = False):

# technically _sanitize_column expects a label, not a position,
# but the behavior is the same as long as we pass broadcast=False
value = self._sanitize_column(loc, value, broadcast=False)
NDFrame._iset_item(self, loc, value)
NDFrame._iset_item(self, loc, value, inplace=inplace)

# check if we are modifying a copy
# try to set first as we want an invalid
# value exception to occur first
if len(self):
if len(self): # FIXME: this should depend on inplace, right?
self._check_setitem_copy()

def _set_item(self, key, value):
Expand Down
6 changes: 3 additions & 3 deletions pandas/core/generic.py
Original file line number Diff line number Diff line change
Expand Up @@ -3425,7 +3425,7 @@ def _maybe_cache_changed(self, item, value) -> None:
The object has called back to us saying maybe it has changed.
"""
loc = self._info_axis.get_loc(item)
self._mgr.iset(loc, value)
self._mgr.iset(loc, value, inplace=False)

@final
@property
Expand Down Expand Up @@ -3814,8 +3814,8 @@ def _slice(self: FrameOrSeries, slobj: slice, axis=0) -> FrameOrSeries:
result._set_is_copy(self, copy=is_copy)
return result

def _iset_item(self, loc: int, value) -> None:
self._mgr.iset(loc, value)
def _iset_item(self, loc: int, value, inplace: bool_t = False) -> None:
self._mgr.iset(loc, value, inplace=inplace)
self._clear_item_cache()

def _set_item(self, key, value) -> None:
Expand Down
31 changes: 27 additions & 4 deletions pandas/core/indexing.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
from pandas.errors import AbstractMethodError, InvalidIndexError
from pandas.util._decorators import doc

from pandas.core.dtypes.cast import maybe_infer_dtype_type
from pandas.core.dtypes.common import (
is_array_like,
is_hashable,
Expand Down Expand Up @@ -675,8 +676,22 @@ def _ensure_listlike_indexer(self, key, axis=None, value=None):
# GH#38148
keys = self.obj.columns.union(key, sort=False)

# Try to get the right dtype when we do this reindex.
jbrockmendel marked this conversation as resolved.
Show resolved Hide resolved
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

doesn't infer_dtype_from do this?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

that infers a dtype, but we need to pass a scalar fill_value to reindex_axis

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

removed this edit as no longer necessary. i think at this point all the controversial bits are gone and we're down to just the bugfix.

fv = None
if is_scalar(value):
fv = value
else:
dtype = maybe_infer_dtype_type(value)
if dtype is not None:
fv = dtype.type(0) # TODO: or try to just do value[0]?

self.obj._mgr = self.obj._mgr.reindex_axis(
keys, axis=0, copy=False, consolidate=False, only_slice=True
keys,
axis=0,
copy=False,
consolidate=False,
only_slice=True,
fill_value=fv,
)

def __setitem__(self, key, value):
Expand Down Expand Up @@ -1576,7 +1591,6 @@ def _setitem_with_indexer(self, indexer, value, name="iloc"):
# essentially this separates out the block that is needed
# to possibly be modified
if self.ndim > 1 and i == info_axis:

# add the new item, and set the value
# must have all defined axes if we have a scalar
# or a list-like on the non-info axes if we have a
Expand Down Expand Up @@ -1805,6 +1819,13 @@ def _setitem_single_column(self, loc: int, value, plane_indexer):
# multi-dim object
# GH#6149 (null slice), GH#10408 (full bounds)
if com.is_null_slice(pi) or com.is_full_slice(pi, len(self.obj)):
blk = ser._mgr.blocks[0]
if blk._can_hold_element(value) and is_scalar(value):
# FIXME: ExtensionBlock._can_hold_element
# We can do an inplace-setting, do it directly on _values
# to get our underlying
ser._values[plane_indexer] = value
return
ser = value
else:
# set the item, possibly having a dtype change
Expand All @@ -1813,7 +1834,7 @@ def _setitem_single_column(self, loc: int, value, plane_indexer):
ser._maybe_update_cacher(clear=True)

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

def _setitem_single_block(self, indexer, value, name: str):
"""
Expand All @@ -1839,7 +1860,9 @@ def _setitem_single_block(self, indexer, value, name: str):
)
and item_labels.is_unique
):
self.obj[item_labels[indexer[info_axis]]] = value
col = item_labels[indexer[info_axis]]
loc = item_labels.get_loc(col)
self.obj._iset_item(loc, value, inplace=True)
return

indexer = maybe_convert_ix(*indexer)
Expand Down
2 changes: 1 addition & 1 deletion pandas/core/internals/blocks.py
Original file line number Diff line number Diff line change
Expand Up @@ -1724,7 +1724,7 @@ def set_inplace(self, locs, values):
# NB: This is a misnomer, is supposed to be inplace but is not,
# see GH#33457
assert locs.tolist() == [0]
self.values = values
self.values[:] = values

def putmask(
self, mask, new, inplace: bool = False, axis: int = 0, transpose: bool = False
Expand Down
4 changes: 2 additions & 2 deletions pandas/core/internals/managers.py
Original file line number Diff line number Diff line change
Expand Up @@ -1054,7 +1054,7 @@ def idelete(self, indexer):
)
self._rebuild_blknos_and_blklocs()

def iset(self, loc: Union[int, slice, np.ndarray], value):
def iset(self, loc: Union[int, slice, np.ndarray], value, inplace: bool = False):
"""
Set new item in-place. Does not consolidate. Adds new Block if not
contained in the current set of items
Expand Down Expand Up @@ -1106,7 +1106,7 @@ def value_getitem(placement):
for blkno, val_locs in libinternals.get_blkno_placements(blknos, group=True):
blk = self.blocks[blkno]
blk_locs = blklocs[val_locs.indexer]
if blk.should_store(value):
if inplace and blk.should_store(value):
blk.set_inplace(blk_locs, value_getitem(val_locs))
else:
unfit_mgr_locs.append(blk.mgr_locs.as_array[blk_locs])
Expand Down
7 changes: 4 additions & 3 deletions pandas/tests/frame/indexing/test_indexing.py
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,7 @@ def test_setitem_list_of_tuples(self, float_frame):
DataFrame(
[[1, 2, 7, 8], [3, 4, 7, 8], [5, 6, 7, 8]],
columns=["A", "B", "C", "D"],
dtype=np.intp,
),
),
(
Expand Down Expand Up @@ -809,7 +810,7 @@ def test_fancy_getitem_slice_mixed(self, float_frame, float_string_frame):

msg = r"\nA value is trying to be set on a copy of a slice from a DataFrame"
with pytest.raises(com.SettingWithCopyError, match=msg):
sliced["C"] = 4.0
sliced.loc[:, "C"] = 4.0
jreback marked this conversation as resolved.
Show resolved Hide resolved

assert (float_frame["C"] == 4).all()

Expand Down Expand Up @@ -1286,7 +1287,7 @@ def test_iloc_row(self):
# setting it makes it raise/warn
msg = r"\nA value is trying to be set on a copy of a slice from a DataFrame"
with pytest.raises(com.SettingWithCopyError, match=msg):
result[2] = 0.0
result.loc[:, 2] = 0.0

exp_col = df[2].copy()
exp_col[4:8] = 0.0
Expand Down Expand Up @@ -1318,7 +1319,7 @@ def test_iloc_col(self):
# and that we are setting a copy
msg = r"\nA value is trying to be set on a copy of a slice from a DataFrame"
with pytest.raises(com.SettingWithCopyError, match=msg):
result[8] = 0.0
result.loc[:, 8] = 0.0

assert (df[8] == 0).all()

Expand Down
2 changes: 1 addition & 1 deletion pandas/tests/frame/methods/test_rename.py
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,7 @@ def test_rename_multiindex(self):

def test_rename_nocopy(self, float_frame):
jreback marked this conversation as resolved.
Show resolved Hide resolved
renamed = float_frame.rename(columns={"C": "foo"}, copy=False)
renamed["foo"] = 1.0
renamed["foo"][:] = 1.0
jreback marked this conversation as resolved.
Show resolved Hide resolved
assert (float_frame["C"] == 1.0).all()

def test_rename_inplace(self, float_frame):
Expand Down
4 changes: 2 additions & 2 deletions pandas/tests/indexing/test_iloc.py
Original file line number Diff line number Diff line change
Expand Up @@ -704,7 +704,7 @@ def test_identity_slice_returns_new_object(self):
assert sliced_df is not original_df

# should be a shallow copy
original_df["a"] = [4, 4, 4]
original_df.loc[:, "a"] = [4, 4, 4]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same comment as above

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

updated both tests

assert (sliced_df["a"] == 4).all()

original_series = Series([1, 2, 3, 4, 5, 6])
Expand All @@ -728,8 +728,8 @@ def test_series_indexing_zerodim_np_array(self):
result = s.iloc[np.array(0)]
assert result == 1

@pytest.mark.xfail(reason="https://github.com/pandas-dev/pandas/issues/33457")
def test_iloc_setitem_categorical_updates_inplace(self):
# GH#35417
# Mixed dtype ensures we go through take_split_path in setitem_with_indexer
cat = Categorical(["A", "B", "C"])
df = DataFrame({1: cat, 2: [1, 2, 3]})
Expand Down
2 changes: 1 addition & 1 deletion pandas/tests/indexing/test_loc.py
Original file line number Diff line number Diff line change
Expand Up @@ -902,7 +902,7 @@ def test_identity_slice_returns_new_object(self):
assert original_df[:] is not original_df

# should be a shallow copy
original_df["a"] = [4, 4, 4]
original_df["a"][:] = [4, 4, 4]
assert (sliced_df["a"] == 4).all()

# These should not return copies
Expand Down