From 6e8df28bc6a0d2daa2639a7b8cdcef3d2c9d8d92 Mon Sep 17 00:00:00 2001 From: Brock Date: Thu, 14 May 2026 11:03:35 -0700 Subject: [PATCH 1/2] DOC: clarify scalar vs list-like return types for .loc and [] closes #46593 Extend the indexing basics table with rows for the list-like ``DataFrame`` cases, and add a short note to the ``.loc`` docstring explaining that the *form* of the indexer (scalar vs. list-like) is what determines the return type, with the duplicate-labels exception called out. Co-Authored-By: Claude Opus 4.7 (1M context) --- doc/source/user_guide/indexing.rst | 10 ++++++++++ pandas/core/indexing.py | 8 ++++++++ 2 files changed, 18 insertions(+) diff --git a/doc/source/user_guide/indexing.rst b/doc/source/user_guide/indexing.rst index b123e381f082a..de8006d2168af 100644 --- a/doc/source/user_guide/indexing.rst +++ b/doc/source/user_guide/indexing.rst @@ -120,6 +120,16 @@ indexing pandas objects with ``[]``: Series, ``series[label]``, scalar value DataFrame, ``frame[colname]``, ``Series`` corresponding to colname + DataFrame, ``frame[[colname]]``, ``DataFrame`` with columns corresponding to ``[colname]`` + DataFrame, ``frame[list_of_colnames]``, ``DataFrame`` with columns corresponding to ``list_of_colnames`` + +The same principle applies to label-based selection with ``.loc``: a +list-like of labels preserves the corresponding axis (so +``df.loc[:, ["A"]]`` returns a ``DataFrame``, even when the list contains a +single label), while a scalar label reduces the axis when labels on that +axis are unique (so ``df.loc[:, "A"]`` typically returns a ``Series``; if +``"A"`` is duplicated on the axis, a ``DataFrame`` is returned instead). +See :ref:`indexing.label` for details. Here we construct a simple time series data set to use for illustrating the indexing functionality: diff --git a/pandas/core/indexing.py b/pandas/core/indexing.py index a6b1815c8c257..dc68a92263c9f 100644 --- a/pandas/core/indexing.py +++ b/pandas/core/indexing.py @@ -1333,6 +1333,14 @@ class _LocIndexer(_LocationIndexer): - A ``callable`` function with one argument (the calling Series or DataFrame) and that returns valid output for indexing (one of the above) + The *form* of the indexer, not the number of items it selects, + determines the return type. A list-like of labels preserves the + corresponding axis, so ``df.loc[:, ["A"]]`` returns a ``DataFrame`` + even when the list contains a single label. A scalar label reduces + the axis when labels on that axis are unique, so ``df.loc[:, "A"]`` + typically returns a ``Series`` (if ``"A"`` is duplicated, the axis + is preserved and a ``DataFrame`` is returned instead). + See more at :ref:`Selection by Label `. Raises From 4d10257791425d117db464ea22d72b9dac444a64 Mon Sep 17 00:00:00 2001 From: Brock Date: Sat, 16 May 2026 08:16:36 -0700 Subject: [PATCH 2/2] DOC: replace prose with doctest examples for .loc column selection Per reviewer feedback (@mroeschke, @CloseChoice), swap the prose paragraph for a doctest-checked example pair contrasting ``df.loc[:, "max_speed"]`` (Series) with ``df.loc[:, ["max_speed"]]`` (DataFrame), so the documented behavior can't drift from reality. Co-Authored-By: Claude Opus 4.7 (1M context) --- pandas/core/indexing.py | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/pandas/core/indexing.py b/pandas/core/indexing.py index dc68a92263c9f..5bcb8078870bf 100644 --- a/pandas/core/indexing.py +++ b/pandas/core/indexing.py @@ -1333,14 +1333,6 @@ class _LocIndexer(_LocationIndexer): - A ``callable`` function with one argument (the calling Series or DataFrame) and that returns valid output for indexing (one of the above) - The *form* of the indexer, not the number of items it selects, - determines the return type. A list-like of labels preserves the - corresponding axis, so ``df.loc[:, ["A"]]`` returns a ``DataFrame`` - even when the list contains a single label. A scalar label reduces - the axis when labels on that axis are unique, so ``df.loc[:, "A"]`` - typically returns a ``Series`` (if ``"A"`` is duplicated, the axis - is preserved and a ``DataFrame`` is returned instead). - See more at :ref:`Selection by Label `. Raises @@ -1387,6 +1379,22 @@ class _LocIndexer(_LocationIndexer): viper 4 5 sidewinder 7 8 + Single column label. Note this returns the column as a Series. + + >>> df.loc[:, "max_speed"] + cobra 1 + viper 4 + sidewinder 7 + Name: max_speed, dtype: int64 + + List with a single column label. Note this returns a DataFrame. + + >>> df.loc[:, ["max_speed"]] + max_speed + cobra 1 + viper 4 + sidewinder 7 + Single label for row and column >>> df.loc["cobra", "shield"]