Skip to content

Commit 40a7d64

Browse files
committed
BUG: refactor _is_key_type_compatible and update test for MultiIndex datetime/date type checking (GH#55969)
1 parent 15a73e1 commit 40a7d64

File tree

2 files changed

+36
-15
lines changed

2 files changed

+36
-15
lines changed

pandas/core/indexes/multi.py

Lines changed: 20 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
lib,
3232
)
3333
from pandas._libs.hashtable import duplicated
34+
from pandas._libs.tslibs.timestamps import Timestamp
3435
from pandas._typing import (
3536
AnyAll,
3637
AnyArrayLike,
@@ -3611,25 +3612,34 @@ def maybe_mi_droplevels(indexer, levels):
36113612

36123613
def _is_key_type_compatible(self, key, level):
36133614
"""
3614-
Return True if the key type is compatible with the type of the level's values.
3615+
Return True if the key is compatible with the type of the level's values.
36153616
"""
36163617
if len(self.levels[level]) == 0:
36173618
return True # nothing to compare
3618-
level_type = type(self.levels[level][0])
36193619

3620-
# Same type → OK
3621-
if isinstance(key, level_type):
3620+
level_type = self.levels[level][0]
3621+
3622+
# Allow slices (used in partial indexing)
3623+
if isinstance(key, slice):
36223624
return True
3623-
# Allow Python int for numpy integer types
3624-
if isinstance(level_type, np.integer) and isinstance(key, int):
3625+
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+
):
36253631
return True
36263632

3627-
# Allow Python float for numpy float types
3628-
if isinstance(level_type, np.floating) and isinstance(key, float):
3633+
# numeric compatibility
3634+
if np.issubdtype(type(level_type), np.integer) and isinstance(key, int):
3635+
return True
3636+
if np.issubdtype(type(level_type), np.floating) and isinstance(
3637+
key, (int, float)
3638+
):
36293639
return True
36303640

3631-
# Allow subclasses of datetime.date for datetime levels
3632-
if isinstance(level_type, datetime.date) and isinstance(key, datetime.date):
3641+
# string compatibility
3642+
if isinstance(level_type, str) and isinstance(key, str):
36333643
return True
36343644

36353645
return False
Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import datetime
1+
import datetime as dt
22

33
import numpy as np
44
import pytest
@@ -7,9 +7,20 @@
77

88

99
def test_multiindex_date_npdatetime_mismatch_raises():
10-
idx = pd.MultiIndex.from_product(
11-
[[datetime.date(2023, 11, 1)], ["A"], ["C"]], names=["date", "t1", "t2"]
10+
dates = [dt.date(2023, 11, 1), dt.date(2023, 11, 1), dt.date(2023, 11, 2)]
11+
t1 = ["A", "B", "C"]
12+
t2 = ["C", "D", "E"]
13+
vals = [10, 20, 30]
14+
15+
df = pd.DataFrame(
16+
data=np.array([dates, t1, t2, vals]).T, columns=["dates", "t1", "t2", "vals"]
1217
)
13-
df = pd.DataFrame({"vals": [1]}, index=idx)
14-
with pytest.raises(TypeError, match="Type mismatch"):
18+
df.set_index(["dates", "t1", "t2"], inplace=True)
19+
20+
# Exact type match
21+
result = df.loc[(dt.date(2023, 11, 1), "A", "C")]
22+
assert result["vals"] == 10
23+
24+
# TypeError
25+
with pytest.raises(KeyError):
1526
df.loc[(np.datetime64("2023-11-01"), "A", "C")]

0 commit comments

Comments
 (0)