diff --git a/doc/source/whatsnew/v1.2.0.rst b/doc/source/whatsnew/v1.2.0.rst index 27511c96faa5a..8491d939f27ac 100644 --- a/doc/source/whatsnew/v1.2.0.rst +++ b/doc/source/whatsnew/v1.2.0.rst @@ -625,6 +625,7 @@ Indexing - Bug in :meth:`DataFrame.iloc` and :meth:`Series.iloc` aligning objects in ``__setitem__`` (:issue:`22046`) - Bug in :meth:`DataFrame.loc` did not raise ``KeyError`` when missing combination was given with ``slice(None)`` for remaining levels (:issue:`19556`) - Bug in :meth:`DataFrame.loc` raising ``TypeError`` when non-integer slice was given to select values from :class:`MultiIndex` (:issue:`25165`, :issue:`24263`) +- Bug in :meth:`Series.at` returning :class:`Series` with one element instead of scalar when index is a :class:`MultiIndex` with one level (:issue:`38053`) - Bug in :meth:`DataFrame.loc` returning and assigning elements in wrong order when indexer is differently ordered than the :class:`MultiIndex` to filter (:issue:`31330`, :issue:`34603`) - Bug in :meth:`DataFrame.loc` and :meth:`DataFrame.__getitem__` raising ``KeyError`` when columns were :class:`MultiIndex` with only one level (:issue:`29749`) diff --git a/pandas/core/indexes/multi.py b/pandas/core/indexes/multi.py index 4b67deb2d102c..cc29c310aa7a2 100644 --- a/pandas/core/indexes/multi.py +++ b/pandas/core/indexes/multi.py @@ -2527,6 +2527,10 @@ def _get_values_for_loc(self, series: "Series", loc, key): if is_scalar(loc): return new_values + if len(new_values) == 1 and not self.nlevels > 1: + # If more than one level left, we can not return a scalar + return new_values[0] + new_index = self[loc] new_index = maybe_droplevels(new_index, key) new_ser = series._constructor(new_values, index=new_index, name=series.name) diff --git a/pandas/tests/indexing/test_scalar.py b/pandas/tests/indexing/test_scalar.py index dd01f4e6a4f49..ce48fd1e5c905 100644 --- a/pandas/tests/indexing/test_scalar.py +++ b/pandas/tests/indexing/test_scalar.py @@ -268,35 +268,41 @@ def test_at_with_tuple_index_set(): assert series.at[1, 2] == 3 -def test_multiindex_at_get(): - # GH 26989 - # DataFrame.at and DataFrame.loc getter works with MultiIndex - df = DataFrame({"a": [1, 2]}, index=[[1, 2], [3, 4]]) - assert df.index.nlevels == 2 - assert df.at[(1, 3), "a"] == 1 - assert df.loc[(1, 3), "a"] == 1 - - # Series.at and Series.loc getter works with MultiIndex - series = df["a"] - assert series.index.nlevels == 2 - assert series.at[1, 3] == 1 - assert series.loc[1, 3] == 1 - - -def test_multiindex_at_set(): - # GH 26989 - # DataFrame.at and DataFrame.loc setter works with MultiIndex - df = DataFrame({"a": [1, 2]}, index=[[1, 2], [3, 4]]) - assert df.index.nlevels == 2 - df.at[(1, 3), "a"] = 3 - assert df.at[(1, 3), "a"] == 3 - df.loc[(1, 3), "a"] = 4 - assert df.loc[(1, 3), "a"] == 4 - - # Series.at and Series.loc setter works with MultiIndex - series = df["a"] - assert series.index.nlevels == 2 - series.at[1, 3] = 5 - assert series.at[1, 3] == 5 - series.loc[1, 3] = 6 - assert series.loc[1, 3] == 6 +class TestMultiIndexScalar: + def test_multiindex_at_get(self): + # GH 26989 + # DataFrame.at and DataFrame.loc getter works with MultiIndex + df = DataFrame({"a": [1, 2]}, index=[[1, 2], [3, 4]]) + assert df.index.nlevels == 2 + assert df.at[(1, 3), "a"] == 1 + assert df.loc[(1, 3), "a"] == 1 + + # Series.at and Series.loc getter works with MultiIndex + series = df["a"] + assert series.index.nlevels == 2 + assert series.at[1, 3] == 1 + assert series.loc[1, 3] == 1 + + def test_multiindex_at_set(self): + # GH 26989 + # DataFrame.at and DataFrame.loc setter works with MultiIndex + df = DataFrame({"a": [1, 2]}, index=[[1, 2], [3, 4]]) + assert df.index.nlevels == 2 + df.at[(1, 3), "a"] = 3 + assert df.at[(1, 3), "a"] == 3 + df.loc[(1, 3), "a"] = 4 + assert df.loc[(1, 3), "a"] == 4 + + # Series.at and Series.loc setter works with MultiIndex + series = df["a"] + assert series.index.nlevels == 2 + series.at[1, 3] = 5 + assert series.at[1, 3] == 5 + series.loc[1, 3] = 6 + assert series.loc[1, 3] == 6 + + def test_multiindex_at_get_one_level(self): + # GH#38053 + s2 = Series((0, 1), index=[[False, True]]) + result = s2.at[False] + assert result == 0