Skip to content

Commit 3f8d6b8

Browse files
committed
[BUG] fix .at for multiindexed series
Addresses: GH26989
1 parent b6cb1a4 commit 3f8d6b8

File tree

3 files changed

+41
-1
lines changed

3 files changed

+41
-1
lines changed

doc/source/whatsnew/v1.1.0.rst

+2
Original file line numberDiff line numberDiff line change
@@ -341,6 +341,8 @@ Indexing
341341
- Fix to preserve the ability to index with the "nearest" method with xarray's CFTimeIndex, an :class:`Index` subclass (`pydata/xarray#3751 <https://github.com/pydata/xarray/issues/3751>`_, :issue:`32905`).
342342
- Bug in :class:`Index` constructor where an unhelpful error message was raised for ``numpy`` scalars (:issue:`33017`)
343343
- Bug in :meth:`DataFrame.lookup` incorrectly raising an ``AttributeError`` when ``frame.index`` or ``frame.columns`` is not unique; this will now raise a ``ValueError`` with a helpful error message (:issue:`33041`)
344+
- Bug in :meth:`Series.at` when used with a :class:`MultiIndex` would raise an exception on valid inputs (:issue:`26989`)
345+
344346

345347
Missing
346348
^^^^^^^

pandas/core/indexing.py

+6-1
Original file line numberDiff line numberDiff line change
@@ -2042,9 +2042,9 @@ def __setitem__(self, key, value):
20422042

20432043
if not isinstance(key, tuple):
20442044
key = _tuplify(self.ndim, key)
2045+
key = list(self._convert_key(key, is_setter=True))
20452046
if len(key) != self.ndim:
20462047
raise ValueError("Not enough indexers for scalar access (setting)!")
2047-
key = list(self._convert_key(key, is_setter=True))
20482048
self.obj._set_value(*key, value=value, takeable=self._takeable)
20492049

20502050

@@ -2057,6 +2057,11 @@ def _convert_key(self, key, is_setter: bool = False):
20572057
Require they keys to be the same type as the index. (so we don't
20582058
fallback)
20592059
"""
2060+
# For series, unpacking key needs to result in the label.
2061+
# This is already the case for len(key) == 1; e.g. (1,)
2062+
if isinstance(self.obj, ABCSeries) and len(key) > 1:
2063+
key = (key,)
2064+
20602065
# allow arbitrary setting
20612066
if is_setter:
20622067
return list(key)

pandas/tests/indexing/test_scalar.py

+33
Original file line numberDiff line numberDiff line change
@@ -302,3 +302,36 @@ def test_iat_dont_wrap_object_datetimelike():
302302
assert result is ser2[1]
303303
assert isinstance(result, timedelta)
304304
assert not isinstance(result, Timedelta)
305+
306+
307+
def test_tuple_indexed_series_at_get():
308+
# GH 26989
309+
# Series.at works with MultiIndex
310+
series = Series([1, 2], index=[(1, 2), (3, 4)])
311+
assert series.at[1, 2] == 1
312+
313+
314+
def test_tuple_indexed_series_at_set():
315+
# GH 26989
316+
# Series.at works with MultiIndex
317+
series = Series([1, 2], index=[(1, 2), (3, 4)])
318+
series.at[1, 2] = 3
319+
assert series.at[1, 2] == 3
320+
321+
322+
def test_multiindex_series_at_get():
323+
# GH 26989
324+
# Series.at works with MultiIndex
325+
series = Series([1, 2], index=[[1, 2], [3, 4]])
326+
assert series.at[1, 3] == 1
327+
assert series.loc[1, 3] == 1
328+
329+
330+
def test_multiindex_series_at_set():
331+
# GH 26989
332+
# Series.at works with MultiIndex
333+
series = Series([1, 2], index=[[1, 2], [3, 4]])
334+
series.at[1, 3] = 3
335+
assert series.at[1, 3] == 3
336+
series.loc[1, 3] = 4
337+
assert series.loc[1, 3] == 4

0 commit comments

Comments
 (0)