|  | 
| 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