Skip to content

Commit fb3e3e6

Browse files
authored
PERF: MultiIndex.values for MI's with DatetimeIndex, TimedeltaIndex, or ExtensionDtype levels (#46288)
1 parent 1ae00c6 commit fb3e3e6

File tree

2 files changed

+17
-4
lines changed

2 files changed

+17
-4
lines changed

doc/source/whatsnew/v1.5.0.rst

+1
Original file line numberDiff line numberDiff line change
@@ -311,6 +311,7 @@ Performance improvements
311311
- Performance improvement in :meth:`.GroupBy.transform` when broadcasting values for user-defined functions (:issue:`45708`)
312312
- Performance improvement in :meth:`.GroupBy.transform` for user-defined functions when only a single group exists (:issue:`44977`)
313313
- Performance improvement in :meth:`MultiIndex.get_locs` (:issue:`45681`, :issue:`46040`)
314+
- Performance improvement in :attr:`MultiIndex.values` when the MultiIndex contains levels of type DatetimeIndex, TimedeltaIndex or ExtensionDtypes (:issue:`46288`)
314315
- Performance improvement in :func:`merge` when left and/or right are empty (:issue:`45838`)
315316
- Performance improvement in :meth:`DataFrame.join` when left and/or right are empty (:issue:`46015`)
316317
- Performance improvement in :meth:`DataFrame.reindex` and :meth:`Series.reindex` when target is a :class:`MultiIndex` (:issue:`46235`)

pandas/core/indexes/multi.py

+16-4
Original file line numberDiff line numberDiff line change
@@ -698,17 +698,29 @@ def _values(self) -> np.ndarray:
698698
values = []
699699

700700
for i in range(self.nlevels):
701-
vals = self._get_level_values(i)
701+
index = self.levels[i]
702+
codes = self.codes[i]
703+
704+
vals = index
702705
if is_categorical_dtype(vals.dtype):
703706
vals = cast("CategoricalIndex", vals)
704707
vals = vals._data._internal_get_values()
708+
709+
if isinstance(vals, ABCDatetimeIndex):
710+
# TODO: this can be removed after Timestamp.freq is removed
711+
# The astype(object) below does not remove the freq from
712+
# the underlying Timestamps so we remove it here to to match
713+
# the behavior of self._get_level_values
714+
vals = vals.copy()
715+
vals.freq = None
716+
705717
if isinstance(vals.dtype, ExtensionDtype) or isinstance(
706718
vals, (ABCDatetimeIndex, ABCTimedeltaIndex)
707719
):
708720
vals = vals.astype(object)
709-
# error: Incompatible types in assignment (expression has type "ndarray",
710-
# variable has type "Index")
711-
vals = np.array(vals, copy=False) # type: ignore[assignment]
721+
722+
vals = np.array(vals, copy=False)
723+
vals = algos.take_nd(vals, codes, fill_value=index._na_value)
712724
values.append(vals)
713725

714726
arr = lib.fast_zip(values)

0 commit comments

Comments
 (0)