Skip to content

Commit c5b7ea7

Browse files
committed
Backport PR pandas-dev#45706: BUG: Frame.iat item_cache invalidation bug
1 parent 8a0fb40 commit c5b7ea7

File tree

3 files changed

+27
-17
lines changed

3 files changed

+27
-17
lines changed

doc/source/whatsnew/v1.4.1.rst

+2-1
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,10 @@ Fixed regressions
1717
- Regression in :meth:`Series.mask` with ``inplace=True`` and ``PeriodDtype`` and an incompatible ``other`` coercing to a common dtype instead of raising (:issue:`45546`)
1818
- Regression in :func:`.assert_frame_equal` not respecting ``check_flags=False`` (:issue:`45554`)
1919
- Regression in :meth:`Series.fillna` with ``downcast=False`` incorrectly downcasting ``object`` dtype (:issue:`45603`)
20+
- Regression in :meth:`DataFrame.iat` setting values leading to not propagating correctly in subsequent lookups (:issue:`45684`)
2021
- Regression in :meth:`DataFrame.loc.__setitem__` losing :class:`Index` name if :class:`DataFrame` was empty before (:issue:`45621`)
2122
- Regression in :func:`join` with overlapping :class:`IntervalIndex` raising an ``InvalidIndexError`` (:issue:`45661`)
22-
-
23+
2324

2425
.. ---------------------------------------------------------------------------
2526

pandas/core/frame.py

+8-16
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,6 @@
9393
)
9494

9595
from pandas.core.dtypes.cast import (
96-
can_hold_element,
9796
construct_1d_arraylike_from_scalar,
9897
construct_2d_arraylike_from_scalar,
9998
find_common_type,
@@ -3864,23 +3863,16 @@ def _set_value(
38643863
try:
38653864
if takeable:
38663865
series = self._ixs(col, axis=1)
3867-
series._set_value(index, value, takeable=True)
3868-
return
3869-
3870-
series = self._get_item_cache(col)
3871-
loc = self.index.get_loc(index)
3872-
dtype = series.dtype
3873-
if isinstance(dtype, np.dtype) and dtype.kind not in ["m", "M"]:
3874-
# otherwise we have EA values, and this check will be done
3875-
# via setitem_inplace
3876-
if not can_hold_element(series._values, value):
3877-
# We'll go through loc and end up casting.
3878-
raise TypeError
3866+
loc = index
3867+
else:
3868+
series = self._get_item_cache(col)
3869+
loc = self.index.get_loc(index)
38793870

3871+
# setitem_inplace will do validation that may raise TypeError
3872+
# or ValueError
38803873
series._mgr.setitem_inplace(loc, value)
3881-
# Note: trying to use series._set_value breaks tests in
3882-
# tests.frame.indexing.test_indexing and tests.indexing.test_partial
3883-
except (KeyError, TypeError):
3874+
3875+
except (KeyError, TypeError, ValueError):
38843876
# set using a non-recursive method & reset the cache
38853877
if takeable:
38863878
self.iloc[index, col] = value

pandas/tests/indexing/test_iat.py

+17
Original file line numberDiff line numberDiff line change
@@ -29,3 +29,20 @@ def test_iat_getitem_series_with_period_index():
2929
expected = ser[index[0]]
3030
result = ser.iat[0]
3131
assert expected == result
32+
33+
34+
def test_iat_setitem_item_cache_cleared(indexer_ial):
35+
# GH#45684
36+
data = {"x": np.arange(8, dtype=np.int64), "y": np.int64(0)}
37+
df = DataFrame(data).copy()
38+
ser = df["y"]
39+
40+
# previously this iat setting would split the block and fail to clear
41+
# the item_cache.
42+
indexer_ial(df)[7, 0] = 9999
43+
44+
indexer_ial(df)[7, 1] = 1234
45+
46+
assert df.iat[7, 1] == 1234
47+
assert ser.iloc[-1] == 1234
48+
assert df.iloc[-1, -1] == 1234

0 commit comments

Comments
 (0)