From 1bf4b5d5c3b9ee6318a5bcd0cd0e5c4e9272bf23 Mon Sep 17 00:00:00 2001 From: Irv Lustig Date: Sun, 16 May 2021 10:20:48 -0400 Subject: [PATCH 01/10] add typing for ExtensionArray.delete --- pandas/core/arrays/base.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pandas/core/arrays/base.py b/pandas/core/arrays/base.py index f337589c35583..b79213cc5d064 100644 --- a/pandas/core/arrays/base.py +++ b/pandas/core/arrays/base.py @@ -1308,7 +1308,7 @@ def __hash__(self) -> int: # ------------------------------------------------------------------------ # Non-Optimized Default Methods - def delete(self: ExtensionArrayT, loc) -> ExtensionArrayT: + def delete(self: ExtensionArrayT, loc: PositionalIndexer) -> ExtensionArrayT: indexer = np.delete(np.arange(len(self)), loc) return self.take(indexer) From 16bcc1a565a1dd272c135a960acdd423269b0c7e Mon Sep 17 00:00:00 2001 From: Irv Lustig Date: Sun, 16 May 2021 10:29:38 -0400 Subject: [PATCH 02/10] typing searchsorted --- pandas/core/arrays/base.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/pandas/core/arrays/base.py b/pandas/core/arrays/base.py index b79213cc5d064..351b576928984 100644 --- a/pandas/core/arrays/base.py +++ b/pandas/core/arrays/base.py @@ -813,7 +813,12 @@ def unique(self: ExtensionArrayT) -> ExtensionArrayT: uniques = unique(self.astype(object)) return self._from_sequence(uniques, dtype=self.dtype) - def searchsorted(self, value, side="left", sorter=None): + def searchsorted( + self, + value: ArrayLike, + side: Literal["left", "right"] = "left", + sorter: ArrayLike | None = None, + ): """ Find indices where elements should be inserted to maintain order. From c0d426f5d37b247e9fa0d795502cadd4dd9c6c13 Mon Sep 17 00:00:00 2001 From: Irv Lustig Date: Mon, 17 May 2021 11:11:54 -0400 Subject: [PATCH 03/10] searchsorted typing updates throughout --- pandas/_typing.py | 6 ++++++ pandas/core/algorithms.py | 16 ++++++++++++---- pandas/core/arrays/_mixins.py | 17 ++++++++++++++--- pandas/core/arrays/base.py | 9 +++++---- pandas/core/arrays/period.py | 18 +++++++++++++++--- pandas/core/arrays/sparse/array.py | 14 +++++++++++++- pandas/core/base.py | 9 ++++++++- pandas/core/indexes/base.py | 6 +++--- pandas/core/indexes/extension.py | 16 ++++++++++++++-- pandas/core/series.py | 9 ++++++++- 10 files changed, 98 insertions(+), 22 deletions(-) diff --git a/pandas/_typing.py b/pandas/_typing.py index 7763b0ceb610a..00e875877709f 100644 --- a/pandas/_typing.py +++ b/pandas/_typing.py @@ -91,6 +91,12 @@ PandasScalar = Union["Period", "Timestamp", "Timedelta", "Interval"] Scalar = Union[PythonScalar, PandasScalar] +# numpy compatible types +NumpyArrayLike = Union[np.ndarray, Sequence[PythonScalar]] +NumpyValueArrayLike = Union[PythonScalar, Sequence[PythonScalar]] +NumpySorter = Union[int, bool, np.ndarray, Sequence[int], Sequence[bool], None] + + # timestamp and timedelta convertible types TimestampConvertibleTypes = Union[ diff --git a/pandas/core/algorithms.py b/pandas/core/algorithms.py index f8f5e5e05bc35..c7713613f46cc 100644 --- a/pandas/core/algorithms.py +++ b/pandas/core/algorithms.py @@ -30,6 +30,8 @@ ArrayLike, DtypeObj, FrameOrSeriesUnion, + NumpySorter, + NumpyValueArrayLike, Scalar, ) from pandas.util._decorators import doc @@ -1507,7 +1509,12 @@ def take( # ------------ # -def searchsorted(arr, value, side="left", sorter=None) -> np.ndarray: +def searchsorted( + arr: ArrayLike, + value: NumpyValueArrayLike, + side: Literal["left", "right"] = "left", + sorter: NumpySorter = None, +) -> np.ndarray: """ Find indices where elements should be inserted to maintain order. @@ -1532,7 +1539,7 @@ def searchsorted(arr, value, side="left", sorter=None) -> np.ndarray: Input array. If `sorter` is None, then it must be sorted in ascending order, otherwise `sorter` must be an array of indices that sort it. - value : array_like + value : array_like or single value Values to insert into `arr`. side : {'left', 'right'}, optional If 'left', the index of the first suitable location found is given. @@ -1573,9 +1580,10 @@ def searchsorted(arr, value, side="left", sorter=None) -> np.ndarray: dtype = value_arr.dtype if is_scalar(value): - value = dtype.type(value) + # We know that value is int + value = cast(int, dtype.type(value)) else: - value = pd_array(value, dtype=dtype) + value = pd_array(cast(ArrayLike, value), dtype=dtype) elif not ( is_object_dtype(arr) or is_numeric_dtype(arr) or is_categorical_dtype(arr) ): diff --git a/pandas/core/arrays/_mixins.py b/pandas/core/arrays/_mixins.py index 7c76a04a605e3..4949435a4defb 100644 --- a/pandas/core/arrays/_mixins.py +++ b/pandas/core/arrays/_mixins.py @@ -2,6 +2,7 @@ from functools import wraps from typing import ( + TYPE_CHECKING, Any, Sequence, TypeVar, @@ -13,7 +14,9 @@ from pandas._libs import lib from pandas._libs.arrays import NDArrayBacked from pandas._typing import ( + ArrayLike, F, + NumpySorter, PositionalIndexer2D, Shape, type_t, @@ -45,6 +48,9 @@ "NDArrayBackedExtensionArrayT", bound="NDArrayBackedExtensionArray" ) +if TYPE_CHECKING: + from typing import Literal + def ravel_compat(meth: F) -> F: """ @@ -176,9 +182,14 @@ def _concat_same_type( return to_concat[0]._from_backing_data(new_values) # type: ignore[arg-type] @doc(ExtensionArray.searchsorted) - def searchsorted(self, value, side="left", sorter=None): - value = self._validate_searchsorted_value(value) - return self._ndarray.searchsorted(value, side=side, sorter=sorter) + def searchsorted( + self, + value: ArrayLike | object, + side: Literal["left", "right"] = "left", + sorter: NumpySorter = None, + ) -> np.ndarray: + npvalue: np.ndarray = cast(np.ndarray, self._validate_searchsorted_value(value)) + return self._ndarray.searchsorted(npvalue, side=side, sorter=sorter) def _validate_searchsorted_value(self, value): return value diff --git a/pandas/core/arrays/base.py b/pandas/core/arrays/base.py index 351b576928984..03010a69bf8e2 100644 --- a/pandas/core/arrays/base.py +++ b/pandas/core/arrays/base.py @@ -26,6 +26,7 @@ ArrayLike, Dtype, FillnaOptions, + NumpySorter, PositionalIndexer, Shape, ) @@ -815,10 +816,10 @@ def unique(self: ExtensionArrayT) -> ExtensionArrayT: def searchsorted( self, - value: ArrayLike, + value: ArrayLike | object, side: Literal["left", "right"] = "left", - sorter: ArrayLike | None = None, - ): + sorter: NumpySorter = None, + ) -> np.ndarray: """ Find indices where elements should be inserted to maintain order. @@ -839,7 +840,7 @@ def searchsorted( Parameters ---------- - value : array_like + value : array_like or a single value Values to insert into `self`. side : {'left', 'right'}, optional If 'left', the index of the first suitable location found is given. diff --git a/pandas/core/arrays/period.py b/pandas/core/arrays/period.py index 101209be30b40..856868f20a4e8 100644 --- a/pandas/core/arrays/period.py +++ b/pandas/core/arrays/period.py @@ -7,6 +7,7 @@ Any, Callable, Sequence, + cast, ) import numpy as np @@ -39,8 +40,10 @@ ) from pandas._typing import ( AnyArrayLike, + ArrayLike, Dtype, NpDtype, + NumpySorter, ) from pandas.util._decorators import ( cache_readonly, @@ -74,6 +77,8 @@ import pandas.core.common as com if TYPE_CHECKING: + from typing import Literal + from pandas.core.arrays import DatetimeArray _shared_doc_kwargs = { @@ -642,12 +647,19 @@ def astype(self, dtype, copy: bool = True): return self.asfreq(dtype.freq) return super().astype(dtype, copy=copy) - def searchsorted(self, value, side="left", sorter=None) -> np.ndarray: - value = self._validate_searchsorted_value(value).view("M8[ns]") + def searchsorted( + self, + value: ArrayLike | object, + side: Literal["left", "right"] = "left", + sorter: NumpySorter = None, + ) -> np.ndarray: + npvalue = cast( + np.ndarray, self._validate_searchsorted_value(value).view("M8[ns]") + ) # Cast to M8 to get datetime-like NaT placement m8arr = self._ndarray.view("M8[ns]") - return m8arr.searchsorted(value, side=side, sorter=sorter) + return m8arr.searchsorted(npvalue, side=side, sorter=sorter) def fillna(self, value=None, method=None, limit=None) -> PeriodArray: if method is not None: diff --git a/pandas/core/arrays/sparse/array.py b/pandas/core/arrays/sparse/array.py index 4847372f18239..208688429b454 100644 --- a/pandas/core/arrays/sparse/array.py +++ b/pandas/core/arrays/sparse/array.py @@ -7,6 +7,7 @@ import numbers import operator from typing import ( + TYPE_CHECKING, Any, Callable, Sequence, @@ -25,8 +26,10 @@ ) from pandas._libs.tslibs import NaT from pandas._typing import ( + ArrayLike, Dtype, NpDtype, + NumpySorter, Scalar, ) from pandas.compat.numpy import function as nv @@ -77,6 +80,9 @@ import pandas.io.formats.printing as printing +if TYPE_CHECKING: + from typing import Literal + # ---------------------------------------------------------------------------- # Array @@ -996,7 +1002,13 @@ def _take_without_fill(self, indices) -> np.ndarray | SparseArray: return taken - def searchsorted(self, v, side="left", sorter=None): + def searchsorted( + self, + v: ArrayLike | object, + side: Literal["left", "right"] = "left", + sorter: NumpySorter = None, + ) -> np.ndarray: + msg = "searchsorted requires high memory usage." warnings.warn(msg, PerformanceWarning, stacklevel=2) if not is_scalar(v): diff --git a/pandas/core/base.py b/pandas/core/base.py index 7a48b1fdfda1e..ddae98eece29c 100644 --- a/pandas/core/base.py +++ b/pandas/core/base.py @@ -23,6 +23,8 @@ DtypeObj, FrameOrSeries, IndexLabel, + NumpySorter, + NumpyValueArrayLike, Shape, final, ) @@ -1225,7 +1227,12 @@ def factorize(self, sort: bool = False, na_sentinel: int | None = -1): """ @doc(_shared_docs["searchsorted"], klass="Index") - def searchsorted(self, value, side="left", sorter=None) -> np.ndarray: + def searchsorted( + self, + value: NumpyValueArrayLike, + side: Literal["left", "right"] = "left", + sorter: NumpySorter = None, + ) -> np.ndarray: return algorithms.searchsorted(self._values, value, side=side, sorter=sorter) def drop_duplicates(self, keep="first"): diff --git a/pandas/core/indexes/base.py b/pandas/core/indexes/base.py index a366b49ce3c55..9f3b59551579c 100644 --- a/pandas/core/indexes/base.py +++ b/pandas/core/indexes/base.py @@ -3545,7 +3545,7 @@ def _get_fill_indexer_searchsorted( "if index and target are monotonic" ) - side = "left" if method == "pad" else "right" + side: Literal["left", "right"] = "left" if method == "pad" else "right" # find exact matches first (this simplifies the algorithm) indexer = self.get_indexer(target) @@ -5721,7 +5721,7 @@ def _maybe_cast_slice_bound(self, label, side: str_t, kind=no_default): return label - def _searchsorted_monotonic(self, label, side: str_t = "left"): + def _searchsorted_monotonic(self, label, side: Literal["left", "right"] = "left"): if self.is_monotonic_increasing: return self.searchsorted(label, side=side) elif self.is_monotonic_decreasing: @@ -5735,7 +5735,7 @@ def _searchsorted_monotonic(self, label, side: str_t = "left"): raise ValueError("index must be monotonic increasing or decreasing") - def get_slice_bound(self, label, side: str_t, kind=None) -> int: + def get_slice_bound(self, label, side: Literal["left", "right"], kind=None) -> int: """ Calculate slice bound that corresponds to given label. diff --git a/pandas/core/indexes/extension.py b/pandas/core/indexes/extension.py index 83998a2792a8a..e81ba083a2e75 100644 --- a/pandas/core/indexes/extension.py +++ b/pandas/core/indexes/extension.py @@ -2,6 +2,7 @@ Shared methods for Index subclasses backed by ExtensionArray. """ from typing import ( + TYPE_CHECKING, Hashable, List, Type, @@ -11,7 +12,10 @@ import numpy as np -from pandas._typing import ArrayLike +from pandas._typing import ( + ArrayLike, + NumpySorter, +) from pandas.compat.numpy import function as nv from pandas.errors import AbstractMethodError from pandas.util._decorators import ( @@ -45,6 +49,9 @@ from pandas.core.indexes.base import Index from pandas.core.ops import get_op_result_name +if TYPE_CHECKING: + from typing import Literal + _T = TypeVar("_T", bound="NDArrayBackedExtensionIndex") @@ -292,7 +299,12 @@ def __getitem__(self, key): deprecate_ndim_indexing(result) return result - def searchsorted(self, value, side="left", sorter=None) -> np.ndarray: + def searchsorted( + self, + value: ArrayLike | object, + side: Literal["left", "right"] = "left", + sorter: NumpySorter = None, + ) -> np.ndarray: # overriding IndexOpsMixin improves performance GH#38083 return self._data.searchsorted(value, side=side, sorter=sorter) diff --git a/pandas/core/series.py b/pandas/core/series.py index c8e9898f9462a..4bab8e29d6217 100644 --- a/pandas/core/series.py +++ b/pandas/core/series.py @@ -42,6 +42,8 @@ FrameOrSeriesUnion, IndexKeyFunc, NpDtype, + NumpySorter, + NumpyValueArrayLike, SingleManager, StorageOptions, ValueKeyFunc, @@ -2755,7 +2757,12 @@ def __rmatmul__(self, other): return self.dot(np.transpose(other)) @doc(base.IndexOpsMixin.searchsorted, klass="Series") - def searchsorted(self, value, side="left", sorter=None) -> np.ndarray: + def searchsorted( + self, + value: NumpyValueArrayLike, + side: Literal["left", "right"] = "left", + sorter: NumpySorter = None, + ) -> np.ndarray: return algorithms.searchsorted(self._values, value, side=side, sorter=sorter) # ------------------------------------------------------------------- From cce79a98c577bf3fc35f5e811ae0a2cd37ccf0bf Mon Sep 17 00:00:00 2001 From: Irv Lustig Date: Mon, 17 May 2021 11:56:45 -0400 Subject: [PATCH 04/10] searchsorted typing updates throughout --- pandas/core/indexes/extension.py | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/pandas/core/indexes/extension.py b/pandas/core/indexes/extension.py index e81ba083a2e75..a1504c2aa5937 100644 --- a/pandas/core/indexes/extension.py +++ b/pandas/core/indexes/extension.py @@ -1,13 +1,12 @@ """ Shared methods for Index subclasses backed by ExtensionArray. """ +from __future__ import annotations + from typing import ( TYPE_CHECKING, Hashable, - List, - Type, TypeVar, - Union, ) import numpy as np @@ -15,6 +14,7 @@ from pandas._typing import ( ArrayLike, NumpySorter, + Scalar, ) from pandas.compat.numpy import function as nv from pandas.errors import AbstractMethodError @@ -127,7 +127,7 @@ def method(self, *args, **kwargs): return method -def inherit_names(names: List[str], delegate, cache: bool = False, wrap: bool = False): +def inherit_names(names: list[str], delegate, cache: bool = False, wrap: bool = False): """ Class decorator to pin attributes from an ExtensionArray to a Index subclass. @@ -237,20 +237,20 @@ class ExtensionIndex(Index): # The base class already passes through to _data: # size, __len__, dtype - _data: Union[IntervalArray, NDArrayBackedExtensionArray] + _data: IntervalArray | NDArrayBackedExtensionArray - _data_cls: Union[ - Type[Categorical], - Type[DatetimeArray], - Type[TimedeltaArray], - Type[PeriodArray], - Type[IntervalArray], - ] + _data_cls: ( + type[Categorical] + | type[DatetimeArray] + | type[TimedeltaArray] + | type[PeriodArray] + | type[IntervalArray] + ) @classmethod def _simple_new( cls, - array: Union[IntervalArray, NDArrayBackedExtensionArray], + array: IntervalArray | NDArrayBackedExtensionArray, name: Hashable = None, ): """ @@ -301,7 +301,7 @@ def __getitem__(self, key): def searchsorted( self, - value: ArrayLike | object, + value: Scalar, side: Literal["left", "right"] = "left", sorter: NumpySorter = None, ) -> np.ndarray: From f37d2159095fe045eea2252365b341f90793d9b6 Mon Sep 17 00:00:00 2001 From: Irv Lustig Date: Tue, 25 May 2021 21:51:53 -0400 Subject: [PATCH 05/10] remove NumpyArrayLike and fix arguments to index.searchsorted --- pandas/_typing.py | 12 ++++++++++-- pandas/core/indexes/extension.py | 2 +- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/pandas/_typing.py b/pandas/_typing.py index 00e875877709f..bf83e2797db25 100644 --- a/pandas/_typing.py +++ b/pandas/_typing.py @@ -92,9 +92,17 @@ Scalar = Union[PythonScalar, PandasScalar] # numpy compatible types -NumpyArrayLike = Union[np.ndarray, Sequence[PythonScalar]] NumpyValueArrayLike = Union[PythonScalar, Sequence[PythonScalar]] -NumpySorter = Union[int, bool, np.ndarray, Sequence[int], Sequence[bool], None] +NumpySorter = Union[ + int, + np.integer, + bool, + np.ndarray, + Sequence[int], + Sequence[np.integer], + Sequence[bool], + None, +] # timestamp and timedelta convertible types diff --git a/pandas/core/indexes/extension.py b/pandas/core/indexes/extension.py index a1504c2aa5937..9118858019530 100644 --- a/pandas/core/indexes/extension.py +++ b/pandas/core/indexes/extension.py @@ -301,7 +301,7 @@ def __getitem__(self, key): def searchsorted( self, - value: Scalar, + value: ArrayLike | Scalar, side: Literal["left", "right"] = "left", sorter: NumpySorter = None, ) -> np.ndarray: From 065454fa44ac9b4a7a2e6aba9a38120cd94c1815 Mon Sep 17 00:00:00 2001 From: Irv Lustig Date: Mon, 31 May 2021 12:37:36 -0400 Subject: [PATCH 06/10] validate_search_sorted fixup --- pandas/core/arrays/_mixins.py | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/pandas/core/arrays/_mixins.py b/pandas/core/arrays/_mixins.py index 4949435a4defb..41e25596a759e 100644 --- a/pandas/core/arrays/_mixins.py +++ b/pandas/core/arrays/_mixins.py @@ -188,11 +188,16 @@ def searchsorted( side: Literal["left", "right"] = "left", sorter: NumpySorter = None, ) -> np.ndarray: - npvalue: np.ndarray = cast(np.ndarray, self._validate_searchsorted_value(value)) + npvalue = self._validate_searchsorted_value(value) return self._ndarray.searchsorted(npvalue, side=side, sorter=sorter) - def _validate_searchsorted_value(self, value): - return value + def _validate_searchsorted_value(self, value: ArrayLike | object) -> np.ndarray: + if isinstance(value, ExtensionArray): + return value.to_numpy() + elif isinstance(value, np.ndarray): + return value + else: + return np.array([value]) @doc(ExtensionArray.shift) def shift(self, periods=1, fill_value=None, axis=0): From cde198ebfbbc33df70764ea2f31f5da6c1800f9c Mon Sep 17 00:00:00 2001 From: Irv Lustig Date: Tue, 1 Jun 2021 08:16:52 -0400 Subject: [PATCH 07/10] fix to NDArrayBackedExtensionArray._validate_searchsorted_value --- pandas/core/arrays/_mixins.py | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/pandas/core/arrays/_mixins.py b/pandas/core/arrays/_mixins.py index 41e25596a759e..821e3b59cb153 100644 --- a/pandas/core/arrays/_mixins.py +++ b/pandas/core/arrays/_mixins.py @@ -18,6 +18,7 @@ F, NumpySorter, PositionalIndexer2D, + PythonScalar, Shape, type_t, ) @@ -191,13 +192,17 @@ def searchsorted( npvalue = self._validate_searchsorted_value(value) return self._ndarray.searchsorted(npvalue, side=side, sorter=sorter) - def _validate_searchsorted_value(self, value: ArrayLike | object) -> np.ndarray: + def _validate_searchsorted_value( + self, value: ArrayLike | object + ) -> np.ndarray | PythonScalar: if isinstance(value, ExtensionArray): return value.to_numpy() elif isinstance(value, np.ndarray): return value else: - return np.array([value]) + # While we also can support DatetimeLikeScalar, numpy.searchsorted + # does not accept that as an argument + return cast(PythonScalar, value) @doc(ExtensionArray.shift) def shift(self, periods=1, fill_value=None, axis=0): From 2d85ddbd00f081ffa45f3f95daf3f736e800b932 Mon Sep 17 00:00:00 2001 From: Irv Lustig Date: Sat, 3 Jul 2021 22:06:53 -0400 Subject: [PATCH 08/10] merge with master - just doc changes --- pandas/core/computation/pytables.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/pandas/core/computation/pytables.py b/pandas/core/computation/pytables.py index 528c7f1a6af20..244dd1cbc7783 100644 --- a/pandas/core/computation/pytables.py +++ b/pandas/core/computation/pytables.py @@ -226,7 +226,11 @@ def stringify(value): if v not in metadata: result = -1 else: - result = metadata.searchsorted(v, side="left") + # error: Incompatible types in assignment (expression has type + # "Union[Any, ndarray[Any, Any]]", variable has type "int") + result = metadata.searchsorted( + v, side="left" + ) # type: ignore[assignment] return TermValue(result, result, "integer") elif kind == "integer": v = int(float(v)) From 6a888ef7add63e65bcb94bb18afd97743e1f4481 Mon Sep 17 00:00:00 2001 From: Irv Lustig Date: Sun, 22 Aug 2021 18:31:11 -0400 Subject: [PATCH 09/10] Small fix to validate_searchsorted_value --- pandas/core/arrays/_mixins.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pandas/core/arrays/_mixins.py b/pandas/core/arrays/_mixins.py index 60b3e7e6fc6b8..f13f1a418c2e9 100644 --- a/pandas/core/arrays/_mixins.py +++ b/pandas/core/arrays/_mixins.py @@ -178,7 +178,7 @@ def searchsorted( def _validate_searchsorted_value( self, value: NumpyValueArrayLike | ExtensionArray - ) -> NumpyValueArrayLike | ExtensionArray: + ) -> NumpyValueArrayLike: if isinstance(value, ExtensionArray): return value.to_numpy() else: From 2370384f814a1ab18ed556697db421745a2a2fab Mon Sep 17 00:00:00 2001 From: Irv Lustig Date: Sun, 22 Aug 2021 21:45:50 -0400 Subject: [PATCH 10/10] add periods to docstrings --- pandas/core/algorithms.py | 4 ++-- pandas/core/arrays/base.py | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/pandas/core/algorithms.py b/pandas/core/algorithms.py index 5053fe47a5f7f..13b39d8162d56 100644 --- a/pandas/core/algorithms.py +++ b/pandas/core/algorithms.py @@ -1565,8 +1565,8 @@ def searchsorted( Returns ------- array of ints or int - If value is array-like, array of insertion points - If value is scalar, a single integer + If value is array-like, array of insertion points. + If value is scalar, a single integer. See Also -------- diff --git a/pandas/core/arrays/base.py b/pandas/core/arrays/base.py index 69f32745c568a..4cc0d4185b22c 100644 --- a/pandas/core/arrays/base.py +++ b/pandas/core/arrays/base.py @@ -850,8 +850,8 @@ def searchsorted( Returns ------- array of ints or int - If value is array-like, array of insertion points - If value is scalar, a single integer + If value is array-like, array of insertion points. + If value is scalar, a single integer. See Also --------