Skip to content

Commit 79f8445

Browse files
committed
REF/PERF: move MultiIndex._tuples into _cache
1 parent f8d3786 commit 79f8445

File tree

2 files changed

+25
-21
lines changed

2 files changed

+25
-21
lines changed

pandas/core/indexes/multi.py

Lines changed: 7 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -243,7 +243,6 @@ class MultiIndex(Index):
243243
_comparables = ["names"]
244244
rename = Index.set_names
245245

246-
_tuples = None
247246
sortorder: Optional[int]
248247

249248
# --------------------------------------------------------------------
@@ -634,16 +633,9 @@ def from_frame(cls, df, sortorder=None, names=None):
634633

635634
# --------------------------------------------------------------------
636635

637-
@property
636+
@cache_readonly
638637
def _values(self):
639638
# We override here, since our parent uses _data, which we don't use.
640-
return self.values
641-
642-
@property
643-
def values(self):
644-
if self._tuples is not None:
645-
return self._tuples
646-
647639
values = []
648640

649641
for i in range(self.nlevels):
@@ -657,8 +649,12 @@ def values(self):
657649
vals = np.array(vals, copy=False)
658650
values.append(vals)
659651

660-
self._tuples = lib.fast_zip(values)
661-
return self._tuples
652+
arr = lib.fast_zip(values)
653+
return arr
654+
655+
@property
656+
def values(self):
657+
return self._values
662658

663659
@property
664660
def array(self):
@@ -737,7 +733,6 @@ def _set_levels(
737733
if any(names):
738734
self._set_names(names)
739735

740-
self._tuples = None
741736
self._reset_cache()
742737

743738
def set_levels(self, levels, level=None, inplace=False, verify_integrity=True):
@@ -895,7 +890,6 @@ def _set_codes(
895890

896891
self._codes = new_codes
897892

898-
self._tuples = None
899893
self._reset_cache()
900894

901895
def set_codes(self, codes, level=None, inplace=False, verify_integrity=True):

pandas/tests/indexes/multi/test_compat.py

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -68,43 +68,53 @@ def test_inplace_mutation_resets_values():
6868

6969
mi1 = MultiIndex(levels=levels, codes=codes)
7070
mi2 = MultiIndex(levels=levels2, codes=codes)
71+
72+
assert "_values" not in mi1._cache
73+
assert "_values" not in mi2._cache
74+
7175
vals = mi1.values.copy()
7276
vals2 = mi2.values.copy()
7377

74-
assert mi1._tuples is not None
78+
assert isinstance(mi1._cache["_values"], np.ndarray)
7579

7680
# Make sure level setting works
7781
new_vals = mi1.set_levels(levels2).values
7882
tm.assert_almost_equal(vals2, new_vals)
7983

80-
# Non-inplace doesn't kill _tuples [implementation detail]
81-
tm.assert_almost_equal(mi1._tuples, vals)
84+
# Non-inplace doesn't drop _values from _cache [implementation detail]
85+
tm.assert_almost_equal(mi1._cache["_values"], vals)
8286

8387
# ...and values is still same too
8488
tm.assert_almost_equal(mi1.values, vals)
8589

86-
# Inplace should kill _tuples
90+
# Inplace should drop _values from _cache
8791
mi1.set_levels(levels2, inplace=True)
92+
assert "_values" not in mi1._cache
8893
tm.assert_almost_equal(mi1.values, vals2)
8994

9095
# Make sure label setting works too
9196
codes2 = [[0, 0, 0, 0, 0, 0], [0, 0, 0, 0, 0, 0]]
9297
exp_values = np.empty((6,), dtype=object)
9398
exp_values[:] = [(1, "a")] * 6
94-
9599
# Must be 1d array of tuples
96100
assert exp_values.shape == (6,)
97-
new_values = mi2.set_codes(codes2).values
101+
102+
new_mi = mi2.set_codes(codes2)
103+
assert "_values" not in new_mi._cache
104+
new_values = new_mi.values
105+
assert "_values" in new_mi._cache
98106

99107
# Not inplace shouldn't change
100-
tm.assert_almost_equal(mi2._tuples, vals2)
108+
tm.assert_almost_equal(mi2._cache["_values"], vals2)
101109

102110
# Should have correct values
103111
tm.assert_almost_equal(exp_values, new_values)
104112

105-
# ...and again setting inplace should kill _tuples, etc
113+
# ...and again setting inplace should drop _values from _cache, etc
106114
mi2.set_codes(codes2, inplace=True)
115+
assert "_values" not in mi2._cache
107116
tm.assert_almost_equal(mi2.values, new_values)
117+
assert "_values" in mi2._cache
108118

109119

110120
def test_ndarray_compat_properties(idx, compat_props):

0 commit comments

Comments
 (0)