|
14 | 14 | intervals_to_interval_bounds,
|
15 | 15 | )
|
16 | 16 | from pandas._libs.missing import NA
|
| 17 | +from pandas._typing import ArrayLike |
17 | 18 | from pandas.compat.numpy import function as nv
|
18 | 19 | from pandas.util._decorators import Appender
|
19 | 20 |
|
20 | 21 | from pandas.core.dtypes.cast import maybe_convert_platform
|
21 | 22 | from pandas.core.dtypes.common import (
|
22 | 23 | is_categorical_dtype,
|
23 | 24 | is_datetime64_any_dtype,
|
| 25 | + is_dtype_equal, |
24 | 26 | is_float_dtype,
|
25 | 27 | is_integer_dtype,
|
26 | 28 | is_interval_dtype,
|
|
29 | 31 | is_scalar,
|
30 | 32 | is_string_dtype,
|
31 | 33 | is_timedelta64_dtype,
|
| 34 | + needs_i8_conversion, |
32 | 35 | pandas_dtype,
|
33 | 36 | )
|
34 | 37 | from pandas.core.dtypes.dtypes import IntervalDtype
|
|
40 | 43 | )
|
41 | 44 | from pandas.core.dtypes.missing import is_valid_nat_for_dtype, isna, notna
|
42 | 45 |
|
43 |
| -from pandas.core.algorithms import take, value_counts |
| 46 | +from pandas.core.algorithms import isin, take, value_counts |
44 | 47 | from pandas.core.arrays.base import ExtensionArray, _extension_array_shared_docs
|
45 | 48 | from pandas.core.arrays.categorical import Categorical
|
46 | 49 | import pandas.core.common as com
|
@@ -1435,6 +1438,43 @@ def contains(self, other):
|
1435 | 1438 | other < self._right if self.open_right else other <= self._right
|
1436 | 1439 | )
|
1437 | 1440 |
|
| 1441 | + def isin(self, values) -> np.ndarray: |
| 1442 | + if not hasattr(values, "dtype"): |
| 1443 | + values = np.array(values) |
| 1444 | + values = extract_array(values, extract_numpy=True) |
| 1445 | + |
| 1446 | + if is_interval_dtype(values.dtype): |
| 1447 | + if self.closed != values.closed: |
| 1448 | + # not comparable -> no overlap |
| 1449 | + return np.zeros(self.shape, dtype=bool) |
| 1450 | + |
| 1451 | + if is_dtype_equal(self.dtype, values.dtype): |
| 1452 | + # GH#38353 instead of casting to object, operating on a |
| 1453 | + # complex128 ndarray is much more performant. |
| 1454 | + |
| 1455 | + # error: "ArrayLike" has no attribute "view" [attr-defined] |
| 1456 | + left = self._combined.view("complex128") # type:ignore[attr-defined] |
| 1457 | + right = values._combined.view("complex128") |
| 1458 | + return np.in1d(left, right) |
| 1459 | + |
| 1460 | + elif needs_i8_conversion(self.left.dtype) ^ needs_i8_conversion( |
| 1461 | + values.left.dtype |
| 1462 | + ): |
| 1463 | + # not comparable -> no overlap |
| 1464 | + return np.zeros(self.shape, dtype=bool) |
| 1465 | + |
| 1466 | + return isin(self.astype(object), values.astype(object)) |
| 1467 | + |
| 1468 | + @property |
| 1469 | + def _combined(self) -> ArrayLike: |
| 1470 | + left = self.left._values.reshape(-1, 1) |
| 1471 | + right = self.right._values.reshape(-1, 1) |
| 1472 | + if needs_i8_conversion(left.dtype): |
| 1473 | + comb = left._concat_same_type([left, right], axis=1) |
| 1474 | + else: |
| 1475 | + comb = np.concatenate([left, right], axis=1) |
| 1476 | + return comb |
| 1477 | + |
1438 | 1478 |
|
1439 | 1479 | def maybe_convert_platform_interval(values):
|
1440 | 1480 | """
|
|
0 commit comments