Skip to content

Commit 73123f9

Browse files
Fix 48224: DataFrame.at must fail when adding more than one value
The problem occurred because when adding a new column to a DataFrame using DataFrame.at, DataFrame._set_value falls back to DataFrame.loc before the InvalidIndexError is raised. The proposed solution makes sure that both, the column index and the row index are determined so that both have a chance to raise.
1 parent 298dac3 commit 73123f9

File tree

3 files changed

+62
-5
lines changed

3 files changed

+62
-5
lines changed

doc/source/whatsnew/v1.6.0.rst

+41-3
Original file line numberDiff line numberDiff line change
@@ -39,10 +39,48 @@ Notable bug fixes
3939

4040
These are bug fixes that might have notable behavior changes.
4141

42-
.. _whatsnew_160.notable_bug_fixes.notable_bug_fix1:
42+
.. _whatsnew_160.notable_bug_fixes.notable_bug_frame_at_new_column_with_slice:
4343

44-
notable_bug_fix1
45-
^^^^^^^^^^^^^^^^
44+
Using :meth:`DataFrame.at` raises when trying to add a new column with multiple values
45+
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
46+
47+
*Old behavior*
48+
49+
.. code-block:: ipython
50+
In [1]: import pandas as pd
51+
52+
In [2]: df = pd.DataFrame({"a": [1, 2, 3], "b": [4, 5, 6]})
53+
54+
In [3]: # should raise InvalidIndexError
55+
df.at[slice(0, 1, None), 'c'] = 7
56+
57+
In [4]: df
58+
Out[4]:
59+
a b c
60+
0 1 4 7.0
61+
1 2 5 7.0
62+
2 3 6 NaN
63+
64+
65+
*New behavior*
66+
67+
.. code-block:: ipython
68+
69+
In [1]: import pandas as pd
70+
71+
In [2]: df = pd.DataFrame({"a": [1, 2, 3], "b": [4, 5, 6]})
72+
73+
In [3]: df.at[slice(0, 1, None), 'c'] = 7
74+
75+
---------------------------------------------------------------------------
76+
InvalidIndexError Traceback (most recent call last)
77+
<ipython-input-3-a89a95224c2b> in <module>
78+
----> 1 df.at[slice(0, 1, None), 'c'] = 7
79+
80+
81+
82+
83+
notable_bug_fix1 ^^^^^^^^^^^^^^^^
4684

4785
.. _whatsnew_160.notable_bug_fixes.notable_bug_fix2:
4886

pandas/core/frame.py

+14-2
Original file line numberDiff line numberDiff line change
@@ -4206,8 +4206,20 @@ def _set_value(
42064206
icol = col
42074207
iindex = cast(int, index)
42084208
else:
4209-
icol = self.columns.get_loc(col)
4210-
iindex = self.index.get_loc(index)
4209+
exception = None
4210+
try:
4211+
icol = self.columns.get_loc(col)
4212+
except (KeyError, TypeError, ValueError) as e:
4213+
exception = e
4214+
4215+
try:
4216+
iindex = self.index.get_loc(index)
4217+
except (KeyError, TypeError, ValueError) as e:
4218+
exception = e
4219+
4220+
if exception is not None:
4221+
raise exception
4222+
42114223
self._mgr.column_setitem(icol, iindex, value)
42124224
self._clear_item_cache()
42134225

pandas/tests/indexing/test_at.py

+7
Original file line numberDiff line numberDiff line change
@@ -214,6 +214,13 @@ def test_at_frame_multiple_columns(self):
214214
with pytest.raises(InvalidIndexError, match=r"slice\(None, None, None\)"):
215215
df.at[5] = [6, 7]
216216

217+
def test_at_frame_new_column_when_index_is_slice(self):
218+
# GH-48224
219+
df = DataFrame({"a": [1, 2, 3], "b": [4, 5, 6]})
220+
221+
with pytest.raises(InvalidIndexError, match=r"slice\(0, 1, None\)"):
222+
df.at[slice(0, 1, None), "c"] = 7
223+
217224
def test_at_getitem_mixed_index_no_fallback(self):
218225
# GH#19860
219226
ser = Series([1, 2, 3, 4, 5], index=["a", "b", "c", 1, 2])

0 commit comments

Comments
 (0)