Skip to content

Commit ffd99d8

Browse files
committed
updated whatsnew list, added more descriptive tests
1 parent 1f4a1c9 commit ffd99d8

File tree

4 files changed

+47
-27
lines changed

4 files changed

+47
-27
lines changed

.gitignore

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -141,5 +141,3 @@ doc/source/savefig/
141141
# Pyodide/WASM related files #
142142
##############################
143143
/.pyodide-xbuildenv-*
144-
145-
*.ipynb

doc/source/whatsnew/v3.0.0.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,14 +80,14 @@ Other enhancements
8080
- Added half-year offset classes :class:`HalfYearBegin`, :class:`HalfYearEnd`, :class:`BHalfYearBegin` and :class:`BHalfYearEnd` (:issue:`60928`)
8181
- Added support to read from Apache Iceberg tables with the new :func:`read_iceberg` function (:issue:`61383`)
8282
- Errors occurring during SQL I/O will now throw a generic :class:`.DatabaseError` instead of the raw Exception type from the underlying driver manager library (:issue:`60748`)
83+
- Implemented :meth:`MultiIndex.searchsorted` (:issue:`14833`)
8384
- Implemented :meth:`Series.str.isascii` and :meth:`Series.str.isascii` (:issue:`59091`)
8485
- Improved deprecation message for offset aliases (:issue:`60820`)
8586
- Multiplying two :class:`DateOffset` objects will now raise a ``TypeError`` instead of a ``RecursionError`` (:issue:`59442`)
8687
- Restore support for reading Stata 104-format and enable reading 103-format dta files (:issue:`58554`)
8788
- Support passing a :class:`Iterable[Hashable]` input to :meth:`DataFrame.drop_duplicates` (:issue:`59237`)
8889
- Support reading Stata 102-format (Stata 1) dta files (:issue:`58978`)
8990
- Support reading Stata 110-format (Stata 7) dta files (:issue:`47176`)
90-
9191
.. ---------------------------------------------------------------------------
9292
.. _whatsnew_300.notable_bug_fixes:
9393

pandas/tests/base/test_misc.py

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -147,13 +147,6 @@ def test_searchsorted(request, index_or_series_obj):
147147
# See gh-12238
148148
obj = index_or_series_obj
149149

150-
# if isinstance(obj, pd.MultiIndex):
151-
# # See gh-14833
152-
# request.applymarker(
153-
# pytest.mark.xfail(
154-
# reason="np.searchsorted doesn't work on pd.MultiIndex: GH 14833"
155-
# )
156-
# )
157150
if obj.dtype.kind == "c" and isinstance(obj, Index):
158151
# TODO: Should Series cases also raise? Looks like they use numpy
159152
# comparison semantics https://github.com/numpy/numpy/issues/15981

pandas/tests/indexes/multi/test_indexing.py

Lines changed: 46 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1031,26 +1031,55 @@ def test_get_loc_namedtuple_behaves_like_tuple():
10311031
assert idx.get_loc(("i5", "i6")) == 2
10321032

10331033

1034-
def test_searchsorted():
1035-
# GH14833
1036-
mi = MultiIndex.from_tuples([("a", 0), ("a", 1), ("b", 0), ("b", 1), ("c", 0)])
1034+
@pytest.fixture
1035+
def mi():
1036+
return MultiIndex.from_tuples([("a", 0), ("a", 1), ("b", 0), ("b", 1), ("c", 0)])
10371037

1038-
assert np.all(mi.searchsorted(("b", 0)) == 2)
1039-
assert np.all(mi.searchsorted(("b", 0), side="right") == 3)
1040-
assert np.all(mi.searchsorted(("a", 0)) == 0)
1041-
assert np.all(mi.searchsorted(("a", -1)) == 0)
1042-
assert np.all(mi.searchsorted(("c", 1)) == 5)
10431038

1044-
result = mi.searchsorted([("a", 1), ("b", 0), ("c", 0)])
1045-
expected = np.array([1, 2, 4], dtype=np.intp)
1046-
tm.assert_numpy_array_equal(result, expected)
1039+
@pytest.mark.parametrize(
1040+
"value, side, expected",
1041+
[
1042+
(("b", 0), "left", 2),
1043+
(("b", 0), "right", 3),
1044+
(("a", 0), "left", 0),
1045+
(("a", -1), "left", 0),
1046+
(("c", 1), "left", 5),
1047+
],
1048+
ids=[
1049+
"b-0-left",
1050+
"b-0-right",
1051+
"a-0-left",
1052+
"a--1-left",
1053+
"c-1-left-beyond",
1054+
],
1055+
)
1056+
def test_searchsorted_single(mi, value, side, expected):
1057+
# GH14833
1058+
result = mi.searchsorted(value, side=side)
1059+
assert np.all(result == expected)
1060+
10471061

1048-
result = mi.searchsorted([("a", 1), ("b", 0), ("c", 0)], side="right")
1049-
expected = np.array([2, 3, 5], dtype=np.intp)
1062+
@pytest.mark.parametrize(
1063+
"values, side, expected",
1064+
[
1065+
([("a", 1), ("b", 0), ("c", 0)], "left", np.array([1, 2, 4], dtype=np.intp)),
1066+
([("a", 1), ("b", 0), ("c", 0)], "right", np.array([2, 3, 5], dtype=np.intp)),
1067+
],
1068+
ids=["list-left", "list-right"],
1069+
)
1070+
def test_searchsorted_list(mi, values, side, expected):
1071+
result = mi.searchsorted(values, side=side)
10501072
tm.assert_numpy_array_equal(result, expected)
10511073

1052-
with pytest.raises(ValueError, match="side must be either 'left' or 'right'"):
1053-
mi.searchsorted(("a", 1), side="middle")
10541074

1055-
with pytest.raises(TypeError, match="value must be a tuple or list"):
1056-
mi.searchsorted("a")
1075+
@pytest.mark.parametrize(
1076+
"value, side, error_type, match",
1077+
[
1078+
(("a", 1), "middle", ValueError, "side must be either 'left' or 'right'"),
1079+
("a", "left", TypeError, "value must be a tuple or list"),
1080+
],
1081+
ids=["invalid-side", "invalid-value-type"],
1082+
)
1083+
def test_searchsorted_invalid(mi, value, side, error_type, match):
1084+
with pytest.raises(error_type, match=match):
1085+
mi.searchsorted(value, side=side)

0 commit comments

Comments
 (0)