Skip to content

Commit 4257ad6

Browse files
Roline-StapnyRoline Stapny Saldanha
andauthored
BUG: Fix Series.reindex losing values when reindexing to MultiIndex (#61969)
Co-authored-by: Roline Stapny Saldanha <[email protected]>
1 parent fcd2a5d commit 4257ad6

File tree

4 files changed

+79
-0
lines changed

4 files changed

+79
-0
lines changed

doc/source/whatsnew/v3.0.0.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -793,6 +793,7 @@ MultiIndex
793793
- Bug in :class:`DataFrame` arithmetic operations in case of unaligned MultiIndex columns (:issue:`60498`)
794794
- Bug in :class:`DataFrame` arithmetic operations with :class:`Series` in case of unaligned MultiIndex (:issue:`61009`)
795795
- Bug in :meth:`MultiIndex.from_tuples` causing wrong output with input of type tuples having NaN values (:issue:`60695`, :issue:`60988`)
796+
- Bug in :meth:`DataFrame.reindex` and :meth:`Series.reindex` where reindexing :class:`Index` to a :class:`MultiIndex` would incorrectly set all values to ``NaN``.(:issue:`60923`)
796797

797798
I/O
798799
^^^

pandas/core/generic.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5373,6 +5373,18 @@ def reindex(
53735373
"""
53745374
# TODO: Decide if we care about having different examples for different
53755375
# kinds
5376+
5377+
# Automatically detect matching level when reindexing from Index to MultiIndex.
5378+
# This prevents values from being incorrectly set to NaN when the source index
5379+
# name matches a index name in the target MultiIndex
5380+
if (
5381+
level is None
5382+
and index is not None
5383+
and isinstance(index, MultiIndex)
5384+
and not isinstance(self.index, MultiIndex)
5385+
and self.index.name in index.names
5386+
):
5387+
level = self.index.name
53765388
self._check_copy_deprecation(copy)
53775389

53785390
if index is not None and columns is not None and labels is not None:

pandas/tests/frame/methods/test_reindex.py

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1258,3 +1258,31 @@ def test_invalid_method(self):
12581258
msg = "Invalid fill method"
12591259
with pytest.raises(ValueError, match=msg):
12601260
df.reindex([1, 0, 2], method="asfreq")
1261+
1262+
def test_reindex_index_name_matches_multiindex_level(self):
1263+
df = DataFrame(
1264+
{"value": [1, 2], "other": ["A", "B"]},
1265+
index=Index([10, 20], name="a"),
1266+
)
1267+
target = MultiIndex.from_product(
1268+
[[10, 20], ["x", "y"]],
1269+
names=["a", "b"],
1270+
)
1271+
1272+
result = df.reindex(index=target)
1273+
expected = DataFrame(
1274+
data={"value": [1, 1, 2, 2], "other": ["A", "A", "B", "B"]},
1275+
index=MultiIndex.from_product([[10, 20], ["x", "y"]], names=["a", "b"]),
1276+
)
1277+
tm.assert_frame_equal(result, expected)
1278+
1279+
def test_reindex_index_name_no_match_multiindex_level(self):
1280+
df = DataFrame({"value": [1, 2]}, index=Index([10, 20], name="different_name"))
1281+
target = MultiIndex.from_product([[10, 20], ["x", "y"]], names=["a", "b"])
1282+
1283+
result = df.reindex(index=target)
1284+
expected = DataFrame(
1285+
data={"value": [np.nan] * 4},
1286+
index=MultiIndex.from_product([[10, 20], ["x", "y"]], names=["a", "b"]),
1287+
)
1288+
tm.assert_frame_equal(result, expected)

pandas/tests/series/methods/test_reindex.py

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -434,3 +434,41 @@ 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+
"name, expected_match_level_a",
441+
[
442+
("a", True),
443+
(None, False),
444+
("x", False),
445+
],
446+
)
447+
def test_reindex_multiindex_automatic_level(name, expected_match_level_a):
448+
series = Series([26.73, 24.255], index=Index([81, 82], name=name))
449+
target = MultiIndex.from_product(
450+
[[81, 82], [np.nan], ["2018-06-01", "2018-07-01"]], names=["a", "b", "c"]
451+
)
452+
453+
result = series.reindex(target)
454+
455+
if expected_match_level_a:
456+
expected = Series(
457+
data=[26.73, 26.73, 24.255, 24.255],
458+
index=MultiIndex.from_product(
459+
[[81, 82], [np.nan], ["2018-06-01", "2018-07-01"]],
460+
names=["a", "b", "c"],
461+
),
462+
dtype=series.dtype,
463+
)
464+
else:
465+
expected = Series(
466+
data=[np.nan] * 4,
467+
index=MultiIndex.from_product(
468+
[[81, 82], [np.nan], ["2018-06-01", "2018-07-01"]],
469+
names=["a", "b", "c"],
470+
),
471+
dtype=series.dtype,
472+
)
473+
474+
tm.assert_series_equal(result, expected)

0 commit comments

Comments
 (0)