|
31 | 31 | lib, |
32 | 32 | ) |
33 | 33 | from pandas._libs.hashtable import duplicated |
34 | | -from pandas._libs.tslibs.timestamps import Timestamp |
35 | 34 | from pandas._typing import ( |
36 | 35 | AnyAll, |
37 | 36 | AnyArrayLike, |
@@ -3612,34 +3611,43 @@ def maybe_mi_droplevels(indexer, levels): |
3612 | 3611 |
|
3613 | 3612 | def _is_key_type_compatible(self, key, level): |
3614 | 3613 | """ |
3615 | | - Return True if the key is compatible with the type of the level's values. |
| 3614 | + Return True if the key type is compatible with the type of the level's values. |
| 3615 | +
|
| 3616 | + Compatible types: |
| 3617 | + - int ↔ np.integer |
| 3618 | + - float ↔ np.floating |
| 3619 | + - str ↔ np.str_ |
| 3620 | + - datetime.date ↔ datetime.datetime |
| 3621 | + - slices (for partial indexing) |
3616 | 3622 | """ |
3617 | 3623 | if len(self.levels[level]) == 0: |
3618 | 3624 | return True # nothing to compare |
3619 | 3625 |
|
3620 | | - level_type = self.levels[level][0] |
| 3626 | + level_val = self.levels[level][0] |
| 3627 | + level_type = type(level_val) |
3621 | 3628 |
|
3622 | | - # Allow slices (used in partial indexing) |
3623 | | - if isinstance(key, slice): |
| 3629 | + # Same type |
| 3630 | + if isinstance(key, level_type): |
3624 | 3631 | return True |
3625 | 3632 |
|
3626 | | - # datetime/date/Timestamp compatibility |
3627 | | - datetime_types = (datetime.date, np.datetime64, Timestamp) |
3628 | | - if isinstance(level_type, datetime_types) and isinstance( |
3629 | | - key, datetime_types + (str,) |
3630 | | - ): |
| 3633 | + # NumPy integer / float / string compatibility |
| 3634 | + if isinstance(level_val, np.integer) and isinstance(key, int): |
| 3635 | + return True |
| 3636 | + if isinstance(level_val, np.floating) and isinstance(key, float): |
| 3637 | + return True |
| 3638 | + if isinstance(level_val, np.str_) and isinstance(key, str): |
3631 | 3639 | return True |
3632 | 3640 |
|
3633 | | - # numeric compatibility |
3634 | | - if np.issubdtype(type(level_type), np.integer) and isinstance(key, int): |
| 3641 | + # Allow subclasses of datetime.date for datetime levels |
| 3642 | + if isinstance(level_val, datetime.date) and isinstance(key, datetime.date): |
3635 | 3643 | return True |
3636 | | - if np.issubdtype(type(level_type), np.floating) and isinstance( |
3637 | | - key, (int, float) |
3638 | | - ): |
| 3644 | + |
| 3645 | + # Allow slices (used internally for partial selection) |
| 3646 | + if isinstance(key, slice): |
3639 | 3647 | return True |
3640 | 3648 |
|
3641 | | - # string compatibility |
3642 | | - if isinstance(level_type, str) and isinstance(key, str): |
| 3649 | + # Allow any NumPy generic types for flexibility |
| 3650 | + if isinstance(key, np.generic): |
3643 | 3651 | return True |
3644 | 3652 |
|
3645 | 3653 | return False |
|
0 commit comments