Skip to content

Commit 4792afd

Browse files
meeseeksmachinejorisvandenbossche
authored andcommitted
Backport PR pandas-dev#27712: BUG: partial string indexing with scalar (pandas-dev#27742)
1 parent cdbf34d commit 4792afd

File tree

6 files changed

+31
-4
lines changed

6 files changed

+31
-4
lines changed

doc/source/whatsnew/v0.25.1.rst

+1-1
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ Interval
8282
Indexing
8383
^^^^^^^^
8484

85-
-
85+
- Bug in partial-string indexing returning a NumPy array rather than a ``Series`` when indexing with a scalar like ``.loc['2015']`` (:issue:`27516`)
8686
-
8787
-
8888

pandas/core/indexes/base.py

+3
Original file line numberDiff line numberDiff line change
@@ -263,6 +263,9 @@ def _outer_indexer(self, left, right):
263263
_infer_as_myclass = False
264264

265265
_engine_type = libindex.ObjectEngine
266+
# whether we support partial string indexing. Overridden
267+
# in DatetimeIndex and PeriodIndex
268+
_supports_partial_string_indexing = False
266269

267270
_accessors = {"str"}
268271

pandas/core/indexes/datetimes.py

+1
Original file line numberDiff line numberDiff line change
@@ -238,6 +238,7 @@ def _join_i8_wrapper(joinf, **kwargs):
238238
)
239239

240240
_engine_type = libindex.DatetimeEngine
241+
_supports_partial_string_indexing = True
241242

242243
_tz = None
243244
_freq = None

pandas/core/indexes/period.py

+1
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,7 @@ class PeriodIndex(DatetimeIndexOpsMixin, Int64Index, PeriodDelegateMixin):
173173
_data = None
174174

175175
_engine_type = libindex.PeriodEngine
176+
_supports_partial_string_indexing = True
176177

177178
# ------------------------------------------------------------------------
178179
# Index Constructors

pandas/core/indexing.py

+14-3
Original file line numberDiff line numberDiff line change
@@ -1726,6 +1726,11 @@ def _is_scalar_access(self, key: Tuple):
17261726
if isinstance(ax, MultiIndex):
17271727
return False
17281728

1729+
if isinstance(k, str) and ax._supports_partial_string_indexing:
1730+
# partial string indexing, df.loc['2000', 'A']
1731+
# should not be considered scalar
1732+
return False
1733+
17291734
if not ax.is_unique:
17301735
return False
17311736

@@ -1741,7 +1746,10 @@ def _get_partial_string_timestamp_match_key(self, key, labels):
17411746
"""Translate any partial string timestamp matches in key, returning the
17421747
new key (GH 10331)"""
17431748
if isinstance(labels, MultiIndex):
1744-
if isinstance(key, str) and labels.levels[0].is_all_dates:
1749+
if (
1750+
isinstance(key, str)
1751+
and labels.levels[0]._supports_partial_string_indexing
1752+
):
17451753
# Convert key '2016-01-01' to
17461754
# ('2016-01-01'[, slice(None, None, None)]+)
17471755
key = tuple([key] + [slice(None)] * (len(labels.levels) - 1))
@@ -1751,7 +1759,10 @@ def _get_partial_string_timestamp_match_key(self, key, labels):
17511759
# (..., slice('2016-01-01', '2016-01-01', None), ...)
17521760
new_key = []
17531761
for i, component in enumerate(key):
1754-
if isinstance(component, str) and labels.levels[i].is_all_dates:
1762+
if (
1763+
isinstance(component, str)
1764+
and labels.levels[i]._supports_partial_string_indexing
1765+
):
17551766
new_key.append(slice(component, component, None))
17561767
else:
17571768
new_key.append(component)
@@ -2340,7 +2351,7 @@ def convert_to_index_sliceable(obj, key):
23402351

23412352
# We might have a datetimelike string that we can translate to a
23422353
# slice here via partial string indexing
2343-
if idx.is_all_dates:
2354+
if idx._supports_partial_string_indexing:
23442355
try:
23452356
return idx._get_string_slice(key)
23462357
except (KeyError, ValueError, NotImplementedError):

pandas/tests/indexes/datetimes/test_partial_slicing.py

+11
Original file line numberDiff line numberDiff line change
@@ -468,3 +468,14 @@ def test_getitem_with_datestring_with_UTC_offset(self, start, end):
468468
with pytest.raises(ValueError, match="The index must be timezone"):
469469
df = df.tz_localize(None)
470470
df[start:end]
471+
472+
def test_slice_reduce_to_series(self):
473+
# GH 27516
474+
df = pd.DataFrame(
475+
{"A": range(24)}, index=pd.date_range("2000", periods=24, freq="M")
476+
)
477+
expected = pd.Series(
478+
range(12), index=pd.date_range("2000", periods=12, freq="M"), name="A"
479+
)
480+
result = df.loc["2000", "A"]
481+
tm.assert_series_equal(result, expected)

0 commit comments

Comments
 (0)