Skip to content

Commit ecabf81

Browse files
author
Roline Stapny Saldanha
committed
BUG: Fix Series.reindex losing values when reindexing to MultiIndex
1 parent e4a03b6 commit ecabf81

File tree

3 files changed

+56
-0
lines changed

3 files changed

+56
-0
lines changed

doc/source/whatsnew/v3.0.0.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -787,6 +787,7 @@ MultiIndex
787787
- Bug in :class:`DataFrame` arithmetic operations in case of unaligned MultiIndex columns (:issue:`60498`)
788788
- Bug in :class:`DataFrame` arithmetic operations with :class:`Series` in case of unaligned MultiIndex (:issue:`61009`)
789789
- Bug in :meth:`MultiIndex.from_tuples` causing wrong output with input of type tuples having NaN values (:issue:`60695`, :issue:`60988`)
790+
- Bug in :meth:`Series.reindex` where reindexing a Series with a named Index to a MultiIndex would incorrectly set all values to ``NaN``. Now correctly preserves values when the source index name matches a target level name (:issue:`60923`)
790791

791792
I/O
792793
^^^

pandas/core/series.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4886,6 +4886,15 @@ def reindex( # type: ignore[override]
48864886
limit: int | None = None,
48874887
tolerance=None,
48884888
) -> Series:
4889+
# Automatically detect matching level when reindexing from Index to MultiIndex.
4890+
# This prevents values from being incorrectly set to NaN when the source index
4891+
# name matches a level name in the target MultiIndex
4892+
if (
4893+
level is None
4894+
and isinstance(index, MultiIndex)
4895+
and self.index.name in index.names
4896+
):
4897+
level = self.index.name
48894898
return super().reindex(
48904899
index=index,
48914900
method=method,

pandas/tests/series/methods/test_reindex.py

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -434,3 +434,49 @@ def test_reindex_expand_nonnano_nat(dtype):
434434
np.array([1, getattr(np, dtype)("nat", "s")], dtype=f"{dtype}[s]")
435435
)
436436
tm.assert_series_equal(result, expected)
437+
438+
439+
@pytest.mark.parametrize(
440+
"idx,expected_match_level_a",
441+
[
442+
# Source index has matching name - should match level "a"
443+
(Index([81, 82], name="a"), True),
444+
# Source index has no name - should not match any level
445+
(Index([81, 82]), False),
446+
# Source index name doesn't match any level - should not match
447+
(Index([81, 82], name="x"), False),
448+
],
449+
)
450+
def test_reindex_multiindex_automatic_level(idx, expected_match_level_a):
451+
"""
452+
Test automatic level detection when reindexing from Index to MultiIndex.
453+
"""
454+
series = Series([26.73, 24.255], index=idx)
455+
target = MultiIndex.from_product(
456+
[[81, 82], [np.nan], ["2018-06-01", "2018-07-01"]], names=["a", "b", "c"]
457+
)
458+
459+
result = series.reindex(target)
460+
461+
if expected_match_level_a:
462+
# Should match behavior of explicit level="a"
463+
expected = series.reindex(target, level="a")
464+
else:
465+
# Should contain all NaN values
466+
expected = Series(np.nan, index=target, dtype=series.dtype)
467+
468+
tm.assert_series_equal(result, expected)
469+
470+
471+
def test_reindex_multiindex_explicit_level_overrides():
472+
"""
473+
Test that explicit level parameter overrides automatic detection.
474+
"""
475+
series = Series([26.73, 24.255], index=Index([81, 82], name="a"))
476+
target = MultiIndex.from_product(
477+
[[81, 82], [np.nan], ["2018-06-01", "2018-07-01"]], names=["a", "b", "c"]
478+
)
479+
480+
result = series.reindex(target, level=0)
481+
expected = series.reindex(target, level="a")
482+
tm.assert_series_equal(result, expected)

0 commit comments

Comments
 (0)