1import numpy as np
2import pytest
3
4import pandas as pd
5from pandas import Index, MultiIndex
6import pandas._testing as tm
7
8
9def test_reindex(idx):
10    result, indexer = idx.reindex(list(idx[:4]))
11    assert isinstance(result, MultiIndex)
12    assert result.names == ["first", "second"]
13    assert [level.name for level in result.levels] == ["first", "second"]
14
15    result, indexer = idx.reindex(list(idx))
16    assert isinstance(result, MultiIndex)
17    assert indexer is None
18    assert result.names == ["first", "second"]
19    assert [level.name for level in result.levels] == ["first", "second"]
20
21
22def test_reindex_level(idx):
23    index = Index(["one"])
24
25    target, indexer = idx.reindex(index, level="second")
26    target2, indexer2 = index.reindex(idx, level="second")
27
28    exp_index = idx.join(index, level="second", how="right")
29    exp_index2 = idx.join(index, level="second", how="left")
30
31    assert target.equals(exp_index)
32    exp_indexer = np.array([0, 2, 4])
33    tm.assert_numpy_array_equal(indexer, exp_indexer, check_dtype=False)
34
35    assert target2.equals(exp_index2)
36    exp_indexer2 = np.array([0, -1, 0, -1, 0, -1])
37    tm.assert_numpy_array_equal(indexer2, exp_indexer2, check_dtype=False)
38
39    with pytest.raises(TypeError, match="Fill method not supported"):
40        idx.reindex(idx, method="pad", level="second")
41
42    with pytest.raises(TypeError, match="Fill method not supported"):
43        index.reindex(index, method="bfill", level="first")
44
45
46def test_reindex_preserves_names_when_target_is_list_or_ndarray(idx):
47    # GH6552
48    idx = idx.copy()
49    target = idx.copy()
50    idx.names = target.names = [None, None]
51
52    other_dtype = pd.MultiIndex.from_product([[1, 2], [3, 4]])
53
54    # list & ndarray cases
55    assert idx.reindex([])[0].names == [None, None]
56    assert idx.reindex(np.array([]))[0].names == [None, None]
57    assert idx.reindex(target.tolist())[0].names == [None, None]
58    assert idx.reindex(target.values)[0].names == [None, None]
59    assert idx.reindex(other_dtype.tolist())[0].names == [None, None]
60    assert idx.reindex(other_dtype.values)[0].names == [None, None]
61
62    idx.names = ["foo", "bar"]
63    assert idx.reindex([])[0].names == ["foo", "bar"]
64    assert idx.reindex(np.array([]))[0].names == ["foo", "bar"]
65    assert idx.reindex(target.tolist())[0].names == ["foo", "bar"]
66    assert idx.reindex(target.values)[0].names == ["foo", "bar"]
67    assert idx.reindex(other_dtype.tolist())[0].names == ["foo", "bar"]
68    assert idx.reindex(other_dtype.values)[0].names == ["foo", "bar"]
69
70
71def test_reindex_lvl_preserves_names_when_target_is_list_or_array():
72    # GH7774
73    idx = pd.MultiIndex.from_product([[0, 1], ["a", "b"]], names=["foo", "bar"])
74    assert idx.reindex([], level=0)[0].names == ["foo", "bar"]
75    assert idx.reindex([], level=1)[0].names == ["foo", "bar"]
76
77
78def test_reindex_lvl_preserves_type_if_target_is_empty_list_or_array():
79    # GH7774
80    idx = pd.MultiIndex.from_product([[0, 1], ["a", "b"]])
81    assert idx.reindex([], level=0)[0].levels[0].dtype.type == np.int64
82    assert idx.reindex([], level=1)[0].levels[1].dtype.type == np.object_
83
84
85def test_reindex_base(idx):
86    idx = idx
87    expected = np.arange(idx.size, dtype=np.intp)
88
89    actual = idx.get_indexer(idx)
90    tm.assert_numpy_array_equal(expected, actual)
91
92    with pytest.raises(ValueError, match="Invalid fill method"):
93        idx.get_indexer(idx, method="invalid")
94
95
96def test_reindex_non_unique():
97    idx = pd.MultiIndex.from_tuples([(0, 0), (1, 1), (1, 1), (2, 2)])
98    a = pd.Series(np.arange(4), index=idx)
99    new_idx = pd.MultiIndex.from_tuples([(0, 0), (1, 1), (2, 2)])
100
101    msg = "cannot handle a non-unique multi-index!"
102    with pytest.raises(ValueError, match=msg):
103        a.reindex(new_idx)
104