MultiIndex#

class MultiIndex#

A multi-level, or hierarchical, index object for pandas objects.

Example#

import pandasCore as pd

# Create MultiIndex
idx = pd.MultiIndex([1, 2, 3], name='my_index')
print(len(idx))  # 3

Attributes#

Attribute

Description

Example

codes

Return the codes (integer positions into levels) for each level

dtypes

Return the dtypes of the levels

empty

Indicator whether MultiIndex is empty

View

has_duplicates

Check if the MultiIndex has duplicate tuples

View

is_monotonic_decreasing

Return if the index is monotonic decreasing

is_monotonic_increasing

Return if the index is monotonic increasing

is_unique

Return if the index has unique values

View

levels

Return the levels (unique values) for each level of the MultiIndex

levshape

A tuple with the length of each level

View

names

Names of the levels in the MultiIndex

View

ndim

Number of dimensions (always 1)

View

nlevels

Number of levels in the MultiIndex

View

shape

Return a tuple of the shape of the underlying data

View

size

Return the number of elements in the MultiIndex

View

str

Vectorized string functions for Index.

View

Construction#

Method

Description

Example

__init__() (*args, **kwargs) | () | (levels: object = None, codes: object = None, sortorder: object = None, names: object = None, dtype: object = None, copy: bool = False, name: object = None, verify_integrity: bool = True)

Create an empty MultiIndex

View

Indexing / Selection#

Method

Description

Example

__getitem__() (index: typing.SupportsInt)

Get tuple at position

take() (indices: list, axis: typing.SupportsInt = 0, allow_fill: bool = True, fill_value: object = None, **kwargs)

Return a new MultiIndex of the values selected by the indices.

View

where() (cond: collections.abc.Sequence[bool], other: object = None)

Replace values where the condition is False.

Data Manipulation#

Method

Description

Example

drop() (codes: list, level: object = None, errors: str = 'raise')

Make new MultiIndex with passed labels removed.

View

droplevel() (level: object = 0)

Return MultiIndex with requested level removed.

View

insert() (loc: typing.SupportsInt, item: tuple)

Make new MultiIndex inserting new item at location.

View

reindex() (target: pandasCore.MultiIndex, method: object = None, level: object = None, limit: object = None, tolerance: object = None)

Conform MultiIndex to new index.

rename() (names: object, *, level: object = None, inplace: bool = False)

Alter MultiIndex name(s).

View

reorder_levels() (order: list)

Rearrange levels using input order.

View

set_names() (names: object, *, level: object = None, inplace: bool = False)

Set Index names.

View

swaplevel() (i: typing.SupportsInt = -2, j: typing.SupportsInt = -1)

Swap level i with level j.

View

Missing Data#

Method

Description

Example

dropna() (how: str = 'any')

Return MultiIndex without NA/NaN values.

fillna() (value: object = None, downcast: object = None)

Fill NA/NaN values with the specified value.

isna() ()

Detect missing values.

View

isnull() ()

Alias for isna()

notna() ()

Detect existing (non-missing) values.

View

notnull() ()

Alias for notna()

Statistics#

Method

Description

Example

max() (axis: object = None, skipna: bool = True, *args, **kwargs)

Return the maximum value of the MultiIndex (lexicographically).

View

min() (axis: object = None, skipna: bool = True, *args, **kwargs)

Return the minimum value of the MultiIndex (lexicographically).

View

nunique() (dropna: bool = True)

Return number of unique tuples in the MultiIndex.

View

value_counts() (normalize: bool = False, sort: bool = True, ascending: bool = False, bins: object = None, dropna: bool = True)

Return a dict containing counts of unique tuples.

View

Aggregation#

Method

Description

Example

groupby() (values: collections.abc.Sequence[str])

Group the index labels by a given array of values.

map() (mapper: collections.abc.Callable, na_action: object = None)

Map values using an input mapping or function.

Comparison#

Method

Description

Example

__eq__() (self, value, /)

Return self==value.

__ge__() (self, value, /)

Return self>=value.

__gt__() (self, value, /)

Return self>value.

__le__() (self, value, /)

Return self<=value.

__lt__() (self, value, /)

Return self<value.

__ne__() (self, value, /)

Return self!=value.

equals() (other: pandasCore.MultiIndex)

Determine if two MultiIndex objects are equal.

Sorting#

Method

Description

Example

argsort() (*args, na_position: str = 'last', **kwargs)

Return the integer indices that would sort the index.

View

searchsorted() (value: tuple, side: str = 'left', sorter: object = None)

Find indices where elements should be inserted to maintain order.

sort_values() (*, return_indexer: bool = False, ascending: bool = True, na_position: str = 'last', key: object = None)

Return a sorted copy of the MultiIndex.

View

Reshaping#

Method

Description

Example

to_frame() (index: bool = True, name: object = None, allow_duplicates: bool = False)

Create a DataFrame with the levels of the MultiIndex as columns.

View

transpose() (*args, **kwargs) | (*args, **kwargs) | (*args, **kwargs)

Return the transpose.

Combining#

Method

Description

Example

append() (other: pandasCore.MultiIndex)

Append a MultiIndex to the current one.

join() (other: pandasCore.MultiIndex, *, how: str = 'left', level: object = None, return_indexers: bool = False, sort: bool = False)

Compute join of two MultiIndex objects.

Time Series#

Method

Description

Example

asof() (label: tuple)

Return the label from the index, or, if not present, the previous one.

diff() (periods: typing.SupportsInt = 1)

Compute the difference between consecutive elements.

shift() (periods: typing.SupportsInt = 1, freq: object = None)

Shift index by desired number of periods.

I/O#

Method

Description

Example

to_flat_index() ()

Convert a MultiIndex to an Index of Tuples.

View

to_list() ()

Alias for tolist()

to_numpy() (dtype: object = None, copy: bool = False, na_value: object = None, **kwargs)

Return a numpy ndarray of the values.

View

to_series() (index: object = None, name: object = None)

Create a Series with both index and values from the index.

tolist() ()

Return a list of tuples.

View

Conversion#

Method

Description

Example

astype() (dtype: str, copy: bool = True)

Cast to a specified dtype.

copy() (names: object = None, deep: bool = False, name: object = None)

Make a copy of this object.

View

infer_objects() (copy: bool = True)

Attempt to infer better dtypes for object columns.

View

view() (cls: object = None)

Return a view of the index.

View

Iteration#

Method

Description

Example

__contains__() (key: tuple)

Check if key is contained in MultiIndex

__iter__() ()

__len__() ()

Return the number of elements

Set Operations#

Method

Description

Example

difference() (other: pandasCore.MultiIndex, sort: object = None)

Return a new MultiIndex with elements from this not in other.

drop_duplicates() (*, keep: str = 'first')

Return MultiIndex with duplicates removed.

View

duplicated() (keep: str = 'first')

Indicate duplicate values.

View

intersection() (other: pandasCore.MultiIndex, sort: bool = False)

Form the intersection of two MultiIndex objects.

isin() (values: list, level: object = None)

Check if values are contained in MultiIndex.

View

symmetric_difference() (other: pandasCore.MultiIndex, result_name: object = None, sort: object = None)

Return the symmetric difference of two MultiIndex objects.

union() (other: pandasCore.MultiIndex, sort: object = None)

Form the union of two MultiIndex objects.

unique() (level: object = None)

Return unique values in the MultiIndex.

View

String Methods#

Method

Description

Example

contains() (key: tuple)

Check if key is contained in MultiIndex.

View

Datetime Methods#

Method

Description

Example

round() (decimals: typing.SupportsInt = 0)

Round the index values to the given number of decimals.

Other Methods#

Method

Description

Example

__hash__() (self, /)

Return hash(self).

__repr__() ()

__str__() ()

all() (*args, **kwargs)

Return whether all elements are True.

any() (*args, **kwargs)

Return whether any element is True.

argmax() (axis: object = None, skipna: bool = True, *args, **kwargs)

Return position of maximum value.

View

argmin() (axis: object = None, skipna: bool = True, *args, **kwargs)

Return position of minimum value.

View

asof_locs() (where: list, mask: collections.abc.Sequence[bool] | None = None)

Return the locations (indices) of labels in the index.

delete() (loc: typing.SupportsInt)

Make new MultiIndex with passed location deleted.

View

equal_levels() (other: pandasCore.MultiIndex)

Return True if the levels of both MultiIndex are the same.

factorize() (sort: bool = False, use_na_sentinel: bool = True)

Encode the object as an enumerated type.

View

format() (name: object = None, formatter: object = None, na_rep: object = None, names: bool = False, space: typing.SupportsInt = 2, sparsify: object = None, adjoin: bool = True)

Render a string representation of the MultiIndex.

View

get_indexer() (target: pandasCore.MultiIndex, method: object = None, limit: object = None, tolerance: object = None)

Compute indexer and mask for new index given the current index.

get_indexer_for() (target: pandasCore.MultiIndex)

Get indexer for target values (alias for get_indexer).

get_indexer_non_unique() (target: pandasCore.MultiIndex)

Compute indexer and mask for new index allowing non-unique values.

get_level_values() (level: object)

Return vector of label values for requested level.

View

get_loc() (key: tuple)

Get integer location for requested label.

View

get_loc_level() (key: str, level: typing.SupportsInt = 0, drop_level: bool = True)

Get location and sliced index for requested label/level.

get_locs() (seq: list)

Get locations for a sequence of labels.

get_slice_bound() (label: tuple, side: str)

Calculate slice bound that corresponds to given label.

holds_integer() ()

Return True if all levels contain integer type

identical() (other: pandasCore.MultiIndex)

Similar to equals, but check that metadata are also the same.

item() ()

Return the first element as a scalar.

memory_usage() (deep: bool = False)

Memory usage of the values.

View

putmask() (mask: collections.abc.Sequence[bool], value: tuple)

Return a new MultiIndex with values put where mask is True.

ravel() (order: str = 'C')

Return a flattened representation.

View

remove_unused_levels() ()

Create new MultiIndex from current with unused levels removed.

repeat() (repeats: typing.SupportsInt, axis: object = None)

Repeat elements of a MultiIndex.

View

set_codes() (codes: list, *, level: object = None, verify_integrity: bool = True)

Set new codes on MultiIndex.

set_levels() (levels: list, *, level: object = None, verify_integrity: bool = True)

Set new levels on MultiIndex.

slice_indexer() (start: object = None, end: object = None, step: object = None)

Compute slice locations for input labels.

View

slice_locs() (start: object = None, end: object = None, step: object = None)

Compute slice locations for input labels.

sort() (ascending: bool = True)

Return a sorted copy of the index.

sortlevel() (level: object = 0, ascending: bool = True, sort_remaining: bool = True, na_position: str = 'first')

Sort MultiIndex at the specified level.

View

truncate() (before: object = None, after: object = None)

Truncate a sorted MultiIndex.

Code Examples#

The following examples are extracted from the test suite.

empty (test_multiindex.py:113)
103    f_print_info("Testing MultiIndex properties...")
104
105    arrays = [['a', 'a', 'b', 'b'], ['one', 'two', 'one', 'two']]
106    mi = pandasCore.MultiIndex.from_arrays(arrays, names=['first', 'second'])
107
108    # Test basic properties
109    ctx.assert_equal(4, mi.size, "property: size")
110    ctx.assert_equal(2, mi.nlevels, "property: nlevels")
111    ctx.assert_equal(1, mi.ndim, "property: ndim")
112    ctx.assert_equal((4,), mi.shape, "property: shape")
113    ctx.assert_false(mi.empty, "property: empty")
114
115    # Test unique/duplicates properties
116    ctx.assert_true(mi.is_unique, "property: is_unique")
117    ctx.assert_false(mi.has_duplicates, "property: has_duplicates")
118
119    # Test with duplicates
120    dup_arrays = [['a', 'a', 'a', 'b'], ['one', 'one', 'two', 'one']]
121    mi_dup = pandasCore.MultiIndex.from_arrays(dup_arrays)
122    ctx.assert_false(mi_dup.is_unique, "property with duplicates: is_unique")
123    ctx.assert_true(mi_dup.has_duplicates, "property with duplicates: has_duplicates")
has_duplicates (test_multiindex.py:117)
107    # Test basic properties
108    ctx.assert_equal(4, mi.size, "property: size")
109    ctx.assert_equal(2, mi.nlevels, "property: nlevels")
110    ctx.assert_equal(1, mi.ndim, "property: ndim")
111    ctx.assert_equal((4,), mi.shape, "property: shape")
112    ctx.assert_false(mi.empty, "property: empty")
113
114    # Test unique/duplicates properties
115    ctx.assert_true(mi.is_unique, "property: is_unique")
116    ctx.assert_false(mi.has_duplicates, "property: has_duplicates")
117
118    # Test with duplicates
119    dup_arrays = [['a', 'a', 'a', 'b'], ['one', 'one', 'two', 'one']]
120    mi_dup = pandasCore.MultiIndex.from_arrays(dup_arrays)
121    ctx.assert_false(mi_dup.is_unique, "property with duplicates: is_unique")
122    ctx.assert_true(mi_dup.has_duplicates, "property with duplicates: has_duplicates")
123
124
125def test_levshape():
126    """Test levshape property"""
is_unique (test_multiindex.py:116)
106    mi = pandasCore.MultiIndex.from_arrays(arrays, names=['first', 'second'])
107
108    # Test basic properties
109    ctx.assert_equal(4, mi.size, "property: size")
110    ctx.assert_equal(2, mi.nlevels, "property: nlevels")
111    ctx.assert_equal(1, mi.ndim, "property: ndim")
112    ctx.assert_equal((4,), mi.shape, "property: shape")
113    ctx.assert_false(mi.empty, "property: empty")
114
115    # Test unique/duplicates properties
116    ctx.assert_true(mi.is_unique, "property: is_unique")
117    ctx.assert_false(mi.has_duplicates, "property: has_duplicates")
118
119    # Test with duplicates
120    dup_arrays = [['a', 'a', 'a', 'b'], ['one', 'one', 'two', 'one']]
121    mi_dup = pandasCore.MultiIndex.from_arrays(dup_arrays)
122    ctx.assert_false(mi_dup.is_unique, "property with duplicates: is_unique")
123    ctx.assert_true(mi_dup.has_duplicates, "property with duplicates: has_duplicates")
124
125
126def test_levshape():
levshape (test_multiindex.py:133)
123    ctx.assert_true(mi_dup.has_duplicates, "property with duplicates: has_duplicates")
124
125
126def test_levshape():
127    """Test levshape property"""
128    f_print_info("Testing levshape property...")
129
130    arrays = [['a', 'a', 'b', 'b'], ['one', 'two', 'one', 'two']]
131    mi = pandasCore.MultiIndex.from_arrays(arrays)
132
133    levshape = mi.levshape
134    # First level has 2 unique values ('a', 'b'), second has 2 ('one', 'two')
135    ctx.assert_equal(2, levshape[0], "levshape: level 0")
136    ctx.assert_equal(2, levshape[1], "levshape: level 1")
137
138
139def test_monotonic():
140    """Test is_monotonic_increasing and is_monotonic_decreasing"""
141    f_print_info("Testing monotonic properties...")
142
143    # Create sorted MultiIndex
names (test_multiindex.py:45)
35    """Test MultiIndex.from_arrays"""
36    f_print_info("Testing MultiIndex.from_arrays...")
37
38    # Create from arrays
39    arrays = [['a', 'a', 'b', 'b'], ['one', 'two', 'one', 'two']]
40    mi = pandasCore.MultiIndex.from_arrays(arrays, names=['first', 'second'])
41
42    # Check basic properties
43    ctx.assert_equal(4, mi.size, "from_arrays: size")
44    ctx.assert_equal(2, mi.nlevels, "from_arrays: nlevels")
45    ctx.assert_list_equal(['first', 'second'], mi.names, "from_arrays: names")
46
47    # Test without names
48    mi2 = pandasCore.MultiIndex.from_arrays(arrays)
49    ctx.assert_equal(4, mi2.size, "from_arrays without names: size")
50
51
52def test_from_tuples():
53    """Test MultiIndex.from_tuples"""
54    f_print_info("Testing MultiIndex.from_tuples...")
ndim (test_multiindex.py:111)
101def test_properties():
102    """Test MultiIndex properties"""
103    f_print_info("Testing MultiIndex properties...")
104
105    arrays = [['a', 'a', 'b', 'b'], ['one', 'two', 'one', 'two']]
106    mi = pandasCore.MultiIndex.from_arrays(arrays, names=['first', 'second'])
107
108    # Test basic properties
109    ctx.assert_equal(4, mi.size, "property: size")
110    ctx.assert_equal(2, mi.nlevels, "property: nlevels")
111    ctx.assert_equal(1, mi.ndim, "property: ndim")
112    ctx.assert_equal((4,), mi.shape, "property: shape")
113    ctx.assert_false(mi.empty, "property: empty")
114
115    # Test unique/duplicates properties
116    ctx.assert_true(mi.is_unique, "property: is_unique")
117    ctx.assert_false(mi.has_duplicates, "property: has_duplicates")
118
119    # Test with duplicates
120    dup_arrays = [['a', 'a', 'a', 'b'], ['one', 'one', 'two', 'one']]
121    mi_dup = pandasCore.MultiIndex.from_arrays(dup_arrays)
nlevels (test_multiindex.py:44)
34def test_from_arrays():
35    """Test MultiIndex.from_arrays"""
36    f_print_info("Testing MultiIndex.from_arrays...")
37
38    # Create from arrays
39    arrays = [['a', 'a', 'b', 'b'], ['one', 'two', 'one', 'two']]
40    mi = pandasCore.MultiIndex.from_arrays(arrays, names=['first', 'second'])
41
42    # Check basic properties
43    ctx.assert_equal(4, mi.size, "from_arrays: size")
44    ctx.assert_equal(2, mi.nlevels, "from_arrays: nlevels")
45    ctx.assert_list_equal(['first', 'second'], mi.names, "from_arrays: names")
46
47    # Test without names
48    mi2 = pandasCore.MultiIndex.from_arrays(arrays)
49    ctx.assert_equal(4, mi2.size, "from_arrays without names: size")
50
51
52def test_from_tuples():
53    """Test MultiIndex.from_tuples"""
54    f_print_info("Testing MultiIndex.from_tuples...")
shape (test_multiindex.py:112)
102    """Test MultiIndex properties"""
103    f_print_info("Testing MultiIndex properties...")
104
105    arrays = [['a', 'a', 'b', 'b'], ['one', 'two', 'one', 'two']]
106    mi = pandasCore.MultiIndex.from_arrays(arrays, names=['first', 'second'])
107
108    # Test basic properties
109    ctx.assert_equal(4, mi.size, "property: size")
110    ctx.assert_equal(2, mi.nlevels, "property: nlevels")
111    ctx.assert_equal(1, mi.ndim, "property: ndim")
112    ctx.assert_equal((4,), mi.shape, "property: shape")
113    ctx.assert_false(mi.empty, "property: empty")
114
115    # Test unique/duplicates properties
116    ctx.assert_true(mi.is_unique, "property: is_unique")
117    ctx.assert_false(mi.has_duplicates, "property: has_duplicates")
118
119    # Test with duplicates
120    dup_arrays = [['a', 'a', 'a', 'b'], ['one', 'one', 'two', 'one']]
121    mi_dup = pandasCore.MultiIndex.from_arrays(dup_arrays)
122    ctx.assert_false(mi_dup.is_unique, "property with duplicates: is_unique")
size (test_interval_multi_range_str.py:122)
112    assert 'IndexStringAccessorType' in str(accessor_type), \
113        f"Expected IndexStringAccessorType, got {accessor_type}"
114    print("  PASSED: type(MultiIndex.str) is IndexStringAccessorType")
115
116def test_multiindex_str_instance_access():
117    """Test MultiIndex instance .str access."""
118    print("Testing MultiIndex instance .str access...")
119
120    # Create a MultiIndex
121    mi = pandasCore.MultiIndex.from_arrays([[1, 2, 3], [4, 5, 6]], names=['first', 'second'])
122    print(f"  Created MultiIndex with {mi.size} elements")
123
124    # Access .str - this should either work or raise an appropriate error
125    # since MultiIndex values are tuples, not strings
126    try:
127        str_methods = mi.str
128        print(f"  mi.str type: {type(str_methods)}")
129        print("  PASSED: MultiIndex.str accessor is accessible")
130    except Exception as e:
131        # Expected to raise error since MultiIndex doesn't contain strings
132        print(f"  Error (expected for non-string data): {e}")
str (test_interval_multi_range_str.py:127)
117    """Test MultiIndex instance .str access."""
118    print("Testing MultiIndex instance .str access...")
119
120    # Create a MultiIndex
121    mi = pandasCore.MultiIndex.from_arrays([[1, 2, 3], [4, 5, 6]], names=['first', 'second'])
122    print(f"  Created MultiIndex with {mi.size} elements")
123
124    # Access .str - this should either work or raise an appropriate error
125    # since MultiIndex values are tuples, not strings
126    try:
127        str_methods = mi.str
128        print(f"  mi.str type: {type(str_methods)}")
129        print("  PASSED: MultiIndex.str accessor is accessible")
130    except Exception as e:
131        # Expected to raise error since MultiIndex doesn't contain strings
132        print(f"  Error (expected for non-string data): {e}")
133        print("  PASSED: Appropriate error raised for non-string Index")
134
135def test_multiindex_str_call_with_data():
136    """Test MultiIndex.str(data) call."""
137    print("Testing MultiIndex.str(data) call...")
__init__ (test_multiindex.py:693)
683# =============================================================================
684# Empty MultiIndex Tests
685# =============================================================================
686
687def test_empty_multiindex():
688    """Test empty MultiIndex"""
689    f_print_info("Testing empty MultiIndex...")
690
691    mi = pandasCore.MultiIndex()
692
693    ctx.assert_equal(0, mi.size, "empty: size")
694    ctx.assert_true(mi.empty, "empty: empty property")
695
696
697# =============================================================================
698# Main Function
699# =============================================================================
700
701def f_main():
take (test_multiindex.py:458)
448# Manipulation Methods Tests
449# =============================================================================
450
451def test_take():
452    """Test take method"""
453    f_print_info("Testing take method...")
454
455    arrays = [['a', 'b', 'c', 'd'], ['one', 'two', 'three', 'four']]
456    mi = pandasCore.MultiIndex.from_arrays(arrays)
457
458    mi_taken = mi.take([0, 2])
459    ctx.assert_equal(2, mi_taken.size, "take: size")
460    ctx.assert_equal(('a', 'one'), mi_taken[0], "take: first element")
461    ctx.assert_equal(('c', 'three'), mi_taken[1], "take: second element")
462
463
464def test_insert():
465    """Test insert method"""
466    f_print_info("Testing insert method...")
467
468    arrays = [['a', 'c'], ['one', 'three']]
drop (test_signature_phase14.py:34)
24    # Should accept name parameter
25    result = mi.copy(names=None, deep=False, name=None)
26    assert result is not None, "copy should return result"
27    print("  copy: OK")
28
29
30def test_drop():
31    """Test drop has level and errors parameters"""
32    mi = pandasCore.MultiIndex.from_tuples([('a', '1'), ('b', '2'), ('c', '3')], names=['x', 'y'])
33    # Should accept level and errors
34    result = mi.drop([('a', '1')], level=None, errors='raise')
35    assert result is not None, "drop should return result"
36    print("  drop: OK")
37
38
39def test_drop_duplicates():
40    """Test drop_duplicates has keyword-only keep"""
41    mi = pandasCore.MultiIndex.from_tuples([('a', '1'), ('a', '1'), ('b', '2')], names=['x', 'y'])
42    # Should accept keep as keyword-only
43    result = mi.drop_duplicates(keep='first')
44    assert result is not None, "drop_duplicates should return result"
droplevel (test_multiindex.py:219)
209def test_droplevel():
210    """Test droplevel method"""
211    f_print_info("Testing droplevel method...")
212
213    arrays = [['a', 'a', 'b', 'b'], ['one', 'two', 'one', 'two']]
214    mi = pandasCore.MultiIndex.from_arrays(arrays, names=['first', 'second'])
215
216    # Drop first level
217    mi_dropped = mi.droplevel(0)
218    ctx.assert_equal(1, mi_dropped.nlevels, "droplevel: nlevels reduced")
219    ctx.assert_list_equal(['second'], mi_dropped.names, "droplevel: correct name remaining")
220
221
222def test_swaplevel():
223    """Test swaplevel method"""
224    f_print_info("Testing swaplevel method...")
225
226    arrays = [['a', 'a', 'b', 'b'], ['one', 'two', 'one', 'two']]
227    mi = pandasCore.MultiIndex.from_arrays(arrays, names=['first', 'second'])
insert (test_multiindex.py:471)
461    ctx.assert_equal(('c', 'three'), mi_taken[1], "take: second element")
462
463
464def test_insert():
465    """Test insert method"""
466    f_print_info("Testing insert method...")
467
468    arrays = [['a', 'c'], ['one', 'three']]
469    mi = pandasCore.MultiIndex.from_arrays(arrays)
470
471    mi_inserted = mi.insert(1, ('b', 'two'))
472    ctx.assert_equal(3, mi_inserted.size, "insert: size")
473    ctx.assert_equal(('b', 'two'), mi_inserted[1], "insert: inserted element")
474
475
476def test_delete():
477    """Test delete method"""
478    f_print_info("Testing delete method...")
479
480    arrays = [['a', 'b', 'c'], ['one', 'two', 'three']]
481    mi = pandasCore.MultiIndex.from_arrays(arrays)
rename (test_signature_phase14.py:159)
149    # Should accept order
150    result = mi.ravel(order='C')
151    assert result is not None, "ravel should return result"
152    print("  ravel: OK")
153
154
155def test_rename():
156    """Test rename has level parameter"""
157    mi = pandasCore.MultiIndex.from_tuples([('a', '1'), ('b', '2')], names=['x', 'y'])
158    # Should accept level
159    result = mi.rename(['new_x', 'new_y'], level=None, inplace=False)
160    assert result is not None, "rename should return result"
161    print("  rename: OK")
162
163
164def test_repeat():
165    """Test repeat has axis parameter"""
166    mi = pandasCore.MultiIndex.from_tuples([('a', '1'), ('b', '2')], names=['x', 'y'])
167    # Should accept axis
168    result = mi.repeat(2, axis=None)
169    assert result is not None, "repeat should return result"
reorder_levels (test_multiindex.py:247)
237    ctx.assert_equal('a', first_tuple[1], "swaplevel: first element level 1")
238
239
240def test_reorder_levels():
241    """Test reorder_levels method"""
242    f_print_info("Testing reorder_levels method...")
243
244    arrays = [['a', 'a'], ['one', 'two'], ['x', 'y']]
245    mi = pandasCore.MultiIndex.from_arrays(arrays, names=['first', 'second', 'third'])
246
247    mi_reordered = mi.reorder_levels([2, 0, 1])
248    ctx.assert_list_equal(['third', 'first', 'second'], mi_reordered.names, "reorder_levels: names reordered")
249
250
251# =============================================================================
252# MultiIndex-specific Methods Tests
253# =============================================================================
254
255def test_to_flat_index():
256    """Test to_flat_index method"""
257    f_print_info("Testing to_flat_index method...")
set_names (test_multiindex.py:180)
170def test_rename_set_names():
171    """Test rename and set_names methods"""
172    f_print_info("Testing rename and set_names methods...")
173
174    arrays = [['a', 'b'], ['one', 'two']]
175    mi = pandasCore.MultiIndex.from_arrays(arrays)
176
177    # Test set_names
178    mi_named = mi.set_names(['first', 'second'])
179    ctx.assert_list_equal(['first', 'second'], mi_named.names, "set_names: names set")
180
181    # Test rename
182    mi_renamed = mi_named.rename(['A', 'B'])
183    ctx.assert_list_equal(['A', 'B'], mi_renamed.names, "rename: names changed")
184
185
186# =============================================================================
187# Level Management Tests
188# =============================================================================
swaplevel (test_multiindex.py:231)
221    ctx.assert_list_equal(['second'], mi_dropped.names, "droplevel: correct name remaining")
222
223
224def test_swaplevel():
225    """Test swaplevel method"""
226    f_print_info("Testing swaplevel method...")
227
228    arrays = [['a', 'a', 'b', 'b'], ['one', 'two', 'one', 'two']]
229    mi = pandasCore.MultiIndex.from_arrays(arrays, names=['first', 'second'])
230
231    mi_swapped = mi.swaplevel(0, 1)
232    ctx.assert_list_equal(['second', 'first'], mi_swapped.names, "swaplevel: names swapped")
233
234    # Check that values are swapped
235    first_tuple = mi_swapped[0]
236    ctx.assert_equal('one', first_tuple[0], "swaplevel: first element level 0")
237    ctx.assert_equal('a', first_tuple[1], "swaplevel: first element level 1")
238
239
240def test_reorder_levels():
241    """Test reorder_levels method"""
isna (test_multiindex.py:526)
516# =============================================================================
517
518def test_na_methods():
519    """Test NA-related methods"""
520    f_print_info("Testing NA-related methods...")
521
522    arrays = [['a', 'b'], ['one', 'two']]
523    mi = pandasCore.MultiIndex.from_arrays(arrays)
524
525    # isna should return all False
526    isna = mi.isna()
527    ctx.assert_list_equal([False, False], isna, "isna: all False")
528
529    # notna should return all True
530    notna = mi.notna()
531    ctx.assert_list_equal([True, True], notna, "notna: all True")
532
533
534# =============================================================================
535# Duplicate Handling Tests
536# =============================================================================
notna (test_multiindex.py:530)
520    f_print_info("Testing NA-related methods...")
521
522    arrays = [['a', 'b'], ['one', 'two']]
523    mi = pandasCore.MultiIndex.from_arrays(arrays)
524
525    # isna should return all False
526    isna = mi.isna()
527    ctx.assert_list_equal([False, False], isna, "isna: all False")
528
529    # notna should return all True
530    notna = mi.notna()
531    ctx.assert_list_equal([True, True], notna, "notna: all True")
532
533
534# =============================================================================
535# Duplicate Handling Tests
536# =============================================================================
537
538def test_drop_duplicates():
539    """Test drop_duplicates method"""
540    f_print_info("Testing drop_duplicates method...")
max (test_multiindex.py:305)
295# =============================================================================
296
297def test_min_max():
298    """Test min and max methods"""
299    f_print_info("Testing min and max methods...")
300
301    arrays = [['a', 'b', 'c'], ['one', 'two', 'three']]
302    mi = pandasCore.MultiIndex.from_arrays(arrays)
303
304    min_val = mi.min()
305    max_val = mi.max()
306
307    f_print_info(f"  min: {min_val}")
308    f_print_info(f"  max: {max_val}")
309
310    # Just verify we get tuples back
311    ctx.assert_equal(2, len(min_val), "min: returns tuple of length 2")
312    ctx.assert_equal(2, len(max_val), "max: returns tuple of length 2")
313
314
315def test_argmin_argmax():
min (test_multiindex.py:304)
294# Statistics Methods Tests
295# =============================================================================
296
297def test_min_max():
298    """Test min and max methods"""
299    f_print_info("Testing min and max methods...")
300
301    arrays = [['a', 'b', 'c'], ['one', 'two', 'three']]
302    mi = pandasCore.MultiIndex.from_arrays(arrays)
303
304    min_val = mi.min()
305    max_val = mi.max()
306
307    f_print_info(f"  min: {min_val}")
308    f_print_info(f"  max: {max_val}")
309
310    # Just verify we get tuples back
311    ctx.assert_equal(2, len(min_val), "min: returns tuple of length 2")
312    ctx.assert_equal(2, len(max_val), "max: returns tuple of length 2")
nunique (test_multiindex.py:340)
330    ctx.assert_true(isinstance(argmax, int), "argmax: returns int")
331
332
333def test_nunique():
334    """Test nunique method"""
335    f_print_info("Testing nunique method...")
336
337    # All unique
338    arrays = [['a', 'b', 'c'], ['one', 'two', 'three']]
339    mi = pandasCore.MultiIndex.from_arrays(arrays)
340    ctx.assert_equal(3, mi.nunique(), "nunique: all unique")
341
342    # With duplicates
343    dup_arrays = [['a', 'a', 'b'], ['one', 'one', 'two']]
344    mi_dup = pandasCore.MultiIndex.from_arrays(dup_arrays)
345    ctx.assert_equal(2, mi_dup.nunique(), "nunique: with duplicates")
346
347
348# =============================================================================
349# Set Operations Tests
350# =============================================================================
value_counts (test_signature_phase14.py:223)
213    # Should accept level
214    result = mi.unique(level=None)
215    assert result is not None, "unique should return result"
216    print("  unique: OK")
217
218
219def test_value_counts():
220    """Test value_counts has normalize and bins parameters"""
221    mi = pandasCore.MultiIndex.from_tuples([('a', '1'), ('a', '1'), ('b', '2')], names=['x', 'y'])
222    # Should accept normalize and bins
223    result = mi.value_counts(normalize=False, sort=True, ascending=False, bins=None, dropna=True)
224    assert result is not None, "value_counts should return result"
225    print("  value_counts: OK")
226
227
228def test_view():
229    """Test view has cls parameter"""
230    mi = pandasCore.MultiIndex.from_tuples([('a', '1'), ('b', '2')], names=['x', 'y'])
231    # Should accept cls
232    result = mi.view(cls=None)
233    assert result is not None, "view should return result"
argsort (test_multiindex.py:510)
500    f_print_info(f"  First after sort: {first}")
501
502
503def test_argsort():
504    """Test argsort method"""
505    f_print_info("Testing argsort method...")
506
507    arrays = [['c', 'a', 'b'], ['three', 'one', 'two']]
508    mi = pandasCore.MultiIndex.from_arrays(arrays)
509
510    indices = mi.argsort()
511    ctx.assert_equal(3, len(indices), "argsort: length")
512
513
514# =============================================================================
515# NA Handling Tests (MultiIndex has no NAs, but API should work)
516# =============================================================================
517
518def test_na_methods():
519    """Test NA-related methods"""
520    f_print_info("Testing NA-related methods...")
sort_values (test_multiindex.py:496)
486    ctx.assert_equal(('c', 'three'), mi_deleted[1], "delete: second element")
487
488
489def test_sort_values():
490    """Test sort_values method"""
491    f_print_info("Testing sort_values method...")
492
493    arrays = [['c', 'a', 'b'], ['three', 'one', 'two']]
494    mi = pandasCore.MultiIndex.from_arrays(arrays)
495
496    mi_sorted = mi.sort_values()
497
498    # First element should be lexicographically smallest
499    first = mi_sorted[0]
500    f_print_info(f"  First after sort: {first}")
501
502
503def test_argsort():
504    """Test argsort method"""
505    f_print_info("Testing argsort method...")
to_frame (test_multiindex.py:275)
265    ctx.assert_equal(('b', 'two'), flat[1], "to_flat_index: second tuple")
266
267
268def test_to_frame():
269    """Test to_frame method"""
270    f_print_info("Testing to_frame method...")
271
272    arrays = [['a', 'b'], ['one', 'two']]
273    mi = pandasCore.MultiIndex.from_arrays(arrays, names=['first', 'second'])
274
275    frame = mi.to_frame()
276    ctx.assert_true('first' in frame or 'level_0' in frame, "to_frame: has column")
277
278
279def test_sortlevel():
280    """Test sortlevel method"""
281    f_print_info("Testing sortlevel method...")
282
283    arrays = [['b', 'a', 'b', 'a'], ['two', 'one', 'one', 'two']]
284    mi = pandasCore.MultiIndex.from_arrays(arrays, names=['first', 'second'])
to_flat_index (test_multiindex.py:262)
252# MultiIndex-specific Methods Tests
253# =============================================================================
254
255def test_to_flat_index():
256    """Test to_flat_index method"""
257    f_print_info("Testing to_flat_index method...")
258
259    arrays = [['a', 'b'], ['one', 'two']]
260    mi = pandasCore.MultiIndex.from_arrays(arrays)
261
262    flat = mi.to_flat_index()
263    ctx.assert_equal(2, len(flat), "to_flat_index: length")
264    ctx.assert_equal(('a', 'one'), flat[0], "to_flat_index: first tuple")
265    ctx.assert_equal(('b', 'two'), flat[1], "to_flat_index: second tuple")
266
267
268def test_to_frame():
269    """Test to_frame method"""
270    f_print_info("Testing to_frame method...")
271
272    arrays = [['a', 'b'], ['one', 'two']]
to_numpy (test_signature_phase14.py:205)
195    # Should accept axis, allow_fill, fill_value
196    result = mi.take([0, 1], axis=0, allow_fill=True, fill_value=None)
197    assert result is not None, "take should return result"
198    print("  take: OK")
199
200
201def test_to_numpy():
202    """Test to_numpy has dtype, copy, na_value parameters"""
203    mi = pandasCore.MultiIndex.from_tuples([('a', '1'), ('b', '2')], names=['x', 'y'])
204    # Should accept dtype, copy, na_value
205    result = mi.to_numpy(dtype=None, copy=False, na_value=None)
206    assert result is not None, "to_numpy should return result"
207    print("  to_numpy: OK")
208
209
210def test_unique():
211    """Test unique has level parameter"""
212    mi = pandasCore.MultiIndex.from_tuples([('a', '1'), ('a', '1'), ('b', '2')], names=['x', 'y'])
213    # Should accept level
214    result = mi.unique(level=None)
215    assert result is not None, "unique should return result"
tolist (test_multiindex.py:623)
613    ctx.assert_equal(mi[0], mi_repeated[1], "repeat: repeated first element")
614
615
616def test_tolist():
617    """Test tolist method"""
618    f_print_info("Testing tolist method...")
619
620    arrays = [['a', 'b'], ['one', 'two']]
621    mi = pandasCore.MultiIndex.from_arrays(arrays)
622
623    result = mi.tolist()
624    ctx.assert_equal(2, len(result), "tolist: length")
625    ctx.assert_equal(('a', 'one'), result[0], "tolist: first tuple")
626
627
628def test_memory_usage():
629    """Test memory_usage method"""
630    f_print_info("Testing memory_usage method...")
631
632    arrays = [['a', 'b'], ['one', 'two']]
633    mi = pandasCore.MultiIndex.from_arrays(arrays)
copy (test_multiindex.py:165)
155# =============================================================================
156# Core Methods Tests
157# =============================================================================
158
159def test_copy():
160    """Test copy method"""
161    f_print_info("Testing copy method...")
162
163    arrays = [['a', 'b'], ['one', 'two']]
164    mi = pandasCore.MultiIndex.from_arrays(arrays, names=['first', 'second'])
165    mi_copy = mi.copy()
166
167    ctx.assert_equal(mi.size, mi_copy.size, "copy: size preserved")
168    ctx.assert_equal(mi.nlevels, mi_copy.nlevels, "copy: nlevels preserved")
169    ctx.assert_list_equal(mi.names, mi_copy.names, "copy: names preserved")
170
171
172def test_rename_set_names():
173    """Test rename and set_names methods"""
174    f_print_info("Testing rename and set_names methods...")
infer_objects (test_signature_phase14.py:95)
 85    # Should accept sortorder
 86    mi = pandasCore.MultiIndex.from_tuples([('a', '1'), ('b', '2')], sortorder=None, names=None)
 87    assert mi is not None, "from_tuples should return MultiIndex"
 88    print("  from_tuples: OK")
 89
 90
 91def test_infer_objects():
 92    """Test infer_objects has copy parameter"""
 93    mi = pandasCore.MultiIndex.from_tuples([('a', '1'), ('b', '2')], names=['x', 'y'])
 94    # Should accept copy
 95    result = mi.infer_objects(copy=True)
 96    assert result is not None, "infer_objects should return result"
 97    print("  infer_objects: OK")
 98
 99
100def test_isin():
101    """Test isin has level parameter"""
102    mi = pandasCore.MultiIndex.from_tuples([('a', '1'), ('b', '2')], names=['x', 'y'])
103    # Should accept level
104    result = mi.isin([('a', '1')], level=None)
105    assert result is not None, "isin should return result"
view (test_signature_phase14.py:232)
222    # Should accept normalize and bins
223    result = mi.value_counts(normalize=False, sort=True, ascending=False, bins=None, dropna=True)
224    assert result is not None, "value_counts should return result"
225    print("  value_counts: OK")
226
227
228def test_view():
229    """Test view has cls parameter"""
230    mi = pandasCore.MultiIndex.from_tuples([('a', '1'), ('b', '2')], names=['x', 'y'])
231    # Should accept cls
232    result = mi.view(cls=None)
233    assert result is not None, "view should return result"
234    print("  view: OK")
235
236
237def f_main():
238    """Run all Phase 14 signature tests"""
239    print("Phase 14: MultiIndex Missing Parameters Tests")
240    print("=" * 50)
241
242    tests = [
drop_duplicates (test_multiindex.py:545)
535# Duplicate Handling Tests
536# =============================================================================
537
538def test_drop_duplicates():
539    """Test drop_duplicates method"""
540    f_print_info("Testing drop_duplicates method...")
541
542    arrays = [['a', 'a', 'b', 'a'], ['one', 'one', 'two', 'one']]
543    mi = pandasCore.MultiIndex.from_arrays(arrays)
544
545    mi_unique = mi.drop_duplicates()
546    ctx.assert_equal(2, mi_unique.size, "drop_duplicates: size")
547
548
549def test_duplicated():
550    """Test duplicated method"""
551    f_print_info("Testing duplicated method...")
552
553    arrays = [['a', 'a', 'b', 'a'], ['one', 'one', 'two', 'one']]
554    mi = pandasCore.MultiIndex.from_arrays(arrays)
duplicated (test_multiindex.py:556)
546    ctx.assert_equal(2, mi_unique.size, "drop_duplicates: size")
547
548
549def test_duplicated():
550    """Test duplicated method"""
551    f_print_info("Testing duplicated method...")
552
553    arrays = [['a', 'a', 'b', 'a'], ['one', 'one', 'two', 'one']]
554    mi = pandasCore.MultiIndex.from_arrays(arrays)
555
556    dups = mi.duplicated()
557    # First (a,one) is not dup, second is, (b,two) is not, third (a,one) is
558    ctx.assert_false(dups[0], "duplicated: first occurrence not duplicate")
559    ctx.assert_true(dups[1], "duplicated: second occurrence is duplicate")
560
561
562def test_unique():
563    """Test unique method"""
564    f_print_info("Testing unique method...")
565
566    arrays = [['a', 'a', 'b', 'a'], ['one', 'one', 'two', 'one']]
isin (test_multiindex.py:584)
574# Other Methods Tests
575# =============================================================================
576
577def test_isin():
578    """Test isin method"""
579    f_print_info("Testing isin method...")
580
581    arrays = [['a', 'b', 'c'], ['one', 'two', 'three']]
582    mi = pandasCore.MultiIndex.from_arrays(arrays)
583
584    result = mi.isin([('a', 'one'), ('c', 'three')])
585    ctx.assert_true(result[0], "isin: (a, one)")
586    ctx.assert_false(result[1], "isin: (b, two) not in set")
587    ctx.assert_true(result[2], "isin: (c, three)")
588
589
590def test_equals():
591    """Test equals method"""
592    f_print_info("Testing equals method...")
593
594    arrays = [['a', 'b'], ['one', 'two']]
unique (test_multiindex.py:569)
559    ctx.assert_true(dups[1], "duplicated: second occurrence is duplicate")
560
561
562def test_unique():
563    """Test unique method"""
564    f_print_info("Testing unique method...")
565
566    arrays = [['a', 'a', 'b', 'a'], ['one', 'one', 'two', 'one']]
567    mi = pandasCore.MultiIndex.from_arrays(arrays)
568
569    mi_unique = mi.unique()
570    ctx.assert_equal(2, mi_unique.size, "unique: size")
571
572
573# =============================================================================
574# Other Methods Tests
575# =============================================================================
576
577def test_isin():
578    """Test isin method"""
579    f_print_info("Testing isin method...")
contains (test_multiindex.py:442)
432    ctx.assert_equal(3, loc2, "get_loc: (b, two)")
433
434
435def test_contains():
436    """Test contains method"""
437    f_print_info("Testing contains method...")
438
439    arrays = [['a', 'b'], ['one', 'two']]
440    mi = pandasCore.MultiIndex.from_arrays(arrays)
441
442    ctx.assert_true(mi.contains(('a', 'one')), "contains: (a, one)")
443    ctx.assert_true(mi.contains(('b', 'two')), "contains: (b, two)")
444    ctx.assert_false(mi.contains(('a', 'two')), "contains: (a, two) not present")
445
446
447# =============================================================================
448# Manipulation Methods Tests
449# =============================================================================
450
451def test_take():
452    """Test take method"""
argmax (test_multiindex.py:323)
313def test_argmin_argmax():
314    """Test argmin and argmax methods"""
315    f_print_info("Testing argmin and argmax methods...")
316
317    arrays = [['c', 'a', 'b'], ['three', 'one', 'two']]
318    mi = pandasCore.MultiIndex.from_arrays(arrays)
319
320    argmin = mi.argmin()
321    argmax = mi.argmax()
322
323    f_print_info(f"  argmin: {argmin}")
324    f_print_info(f"  argmax: {argmax}")
325
326    # Verify we get integer indices
327    ctx.assert_true(isinstance(argmin, int), "argmin: returns int")
328    ctx.assert_true(isinstance(argmax, int), "argmax: returns int")
329
330
331def test_nunique():
argmin (test_multiindex.py:322)
312    ctx.assert_equal(2, len(max_val), "max: returns tuple of length 2")
313
314
315def test_argmin_argmax():
316    """Test argmin and argmax methods"""
317    f_print_info("Testing argmin and argmax methods...")
318
319    arrays = [['c', 'a', 'b'], ['three', 'one', 'two']]
320    mi = pandasCore.MultiIndex.from_arrays(arrays)
321
322    argmin = mi.argmin()
323    argmax = mi.argmax()
324
325    f_print_info(f"  argmin: {argmin}")
326    f_print_info(f"  argmax: {argmax}")
327
328    # Verify we get integer indices
329    ctx.assert_true(isinstance(argmin, int), "argmin: returns int")
330    ctx.assert_true(isinstance(argmax, int), "argmax: returns int")
delete (test_multiindex.py:483)
473    ctx.assert_equal(('b', 'two'), mi_inserted[1], "insert: inserted element")
474
475
476def test_delete():
477    """Test delete method"""
478    f_print_info("Testing delete method...")
479
480    arrays = [['a', 'b', 'c'], ['one', 'two', 'three']]
481    mi = pandasCore.MultiIndex.from_arrays(arrays)
482
483    mi_deleted = mi.delete(1)
484    ctx.assert_equal(2, mi_deleted.size, "delete: size")
485    ctx.assert_equal(('a', 'one'), mi_deleted[0], "delete: first element")
486    ctx.assert_equal(('c', 'three'), mi_deleted[1], "delete: second element")
487
488
489def test_sort_values():
490    """Test sort_values method"""
491    f_print_info("Testing sort_values method...")
492
493    arrays = [['c', 'a', 'b'], ['three', 'one', 'two']]
factorize (test_signature_phase14.py:52)
42    # Should accept keep as keyword-only
43    result = mi.drop_duplicates(keep='first')
44    assert result is not None, "drop_duplicates should return result"
45    print("  drop_duplicates: OK")
46
47
48def test_factorize():
49    """Test factorize has use_na_sentinel parameter"""
50    mi = pandasCore.MultiIndex.from_tuples([('a', '1'), ('b', '2')], names=['x', 'y'])
51    # Should accept use_na_sentinel
52    codes, uniques = mi.factorize(sort=False, use_na_sentinel=True)
53    assert codes is not None, "factorize should return codes"
54    print("  factorize: OK")
55
56
57def test_format():
58    """Test format has formatter and other parameters"""
59    mi = pandasCore.MultiIndex.from_tuples([('a', '1'), ('b', '2')], names=['x', 'y'])
60    # Should accept formatter, na_rep, names, space, sparsify, adjoin
61    result = mi.format(name=None, formatter=None, na_rep=None, names=False, space=2, sparsify=None, adjoin=True)
62    assert result is not None, "format should return result"
format (test_signature_phase14.py:61)
51    # Should accept use_na_sentinel
52    codes, uniques = mi.factorize(sort=False, use_na_sentinel=True)
53    assert codes is not None, "factorize should return codes"
54    print("  factorize: OK")
55
56
57def test_format():
58    """Test format has formatter and other parameters"""
59    mi = pandasCore.MultiIndex.from_tuples([('a', '1'), ('b', '2')], names=['x', 'y'])
60    # Should accept formatter, na_rep, names, space, sparsify, adjoin
61    result = mi.format(name=None, formatter=None, na_rep=None, names=False, space=2, sparsify=None, adjoin=True)
62    assert result is not None, "format should return result"
63    print("  format: OK")
64
65
66def test_from_frame():
67    """Test from_frame has sortorder parameter"""
68    df = {'a': ['x', 'y'], 'b': ['1', '2']}
69    # Should accept sortorder
70    mi = pandasCore.MultiIndex.from_frame(df, sortorder=None, names=None)
71    assert mi is not None, "from_frame should return MultiIndex"
get_level_values (test_multiindex.py:200)
190# =============================================================================
191
192def test_get_level_values():
193    """Test get_level_values method"""
194    f_print_info("Testing get_level_values method...")
195
196    arrays = [['a', 'a', 'b', 'b'], ['one', 'two', 'one', 'two']]
197    mi = pandasCore.MultiIndex.from_arrays(arrays, names=['first', 'second'])
198
199    # Get by index
200    level0_vals = mi.get_level_values(0)
201    ctx.assert_list_equal(['a', 'a', 'b', 'b'], level0_vals, "get_level_values: level 0 by index")
202
203    level1_vals = mi.get_level_values(1)
204    ctx.assert_list_equal(['one', 'two', 'one', 'two'], level1_vals, "get_level_values: level 1 by index")
205
206    # Get by name
207    level_by_name = mi.get_level_values('first')
208    ctx.assert_list_equal(['a', 'a', 'b', 'b'], level_by_name, "get_level_values: level by name")
get_loc (test_multiindex.py:428)
418# =============================================================================
419
420def test_get_loc():
421    """Test get_loc method"""
422    f_print_info("Testing get_loc method...")
423
424    arrays = [['a', 'a', 'b', 'b'], ['one', 'two', 'one', 'two']]
425    mi = pandasCore.MultiIndex.from_arrays(arrays)
426
427    # Get location of specific tuple
428    loc = mi.get_loc(('a', 'one'))
429    ctx.assert_equal(0, loc, "get_loc: (a, one)")
430
431    loc2 = mi.get_loc(('b', 'two'))
432    ctx.assert_equal(3, loc2, "get_loc: (b, two)")
433
434
435def test_contains():
436    """Test contains method"""
437    f_print_info("Testing contains method...")
memory_usage (test_multiindex.py:635)
625    ctx.assert_equal(('a', 'one'), result[0], "tolist: first tuple")
626
627
628def test_memory_usage():
629    """Test memory_usage method"""
630    f_print_info("Testing memory_usage method...")
631
632    arrays = [['a', 'b'], ['one', 'two']]
633    mi = pandasCore.MultiIndex.from_arrays(arrays)
634
635    mem = mi.memory_usage()
636    ctx.assert_true(mem > 0, "memory_usage: positive value")
637
638
639# =============================================================================
640# Magic Methods Tests
641# =============================================================================
642
643def test_magic_methods():
644    """Test magic methods (__len__, __getitem__, __contains__, __iter__)"""
645    f_print_info("Testing magic methods...")
ravel (test_signature_phase14.py:150)
140    # Should accept dropna
141    result = mi.nunique(dropna=True)
142    assert result is not None, "nunique should return result"
143    print("  nunique: OK")
144
145
146def test_ravel():
147    """Test ravel has order parameter"""
148    mi = pandasCore.MultiIndex.from_tuples([('a', '1'), ('b', '2')], names=['x', 'y'])
149    # Should accept order
150    result = mi.ravel(order='C')
151    assert result is not None, "ravel should return result"
152    print("  ravel: OK")
153
154
155def test_rename():
156    """Test rename has level parameter"""
157    mi = pandasCore.MultiIndex.from_tuples([('a', '1'), ('b', '2')], names=['x', 'y'])
158    # Should accept level
159    result = mi.rename(['new_x', 'new_y'], level=None, inplace=False)
160    assert result is not None, "rename should return result"
repeat (test_multiindex.py:610)
600    ctx.assert_false(mi1.equals(mi3), "equals: different MultiIndex")
601
602
603def test_repeat():
604    """Test repeat method"""
605    f_print_info("Testing repeat method...")
606
607    arrays = [['a', 'b'], ['one', 'two']]
608    mi = pandasCore.MultiIndex.from_arrays(arrays)
609
610    mi_repeated = mi.repeat(2)
611    ctx.assert_equal(4, mi_repeated.size, "repeat: size doubled")
612    ctx.assert_equal(mi[0], mi_repeated[0], "repeat: first element")
613    ctx.assert_equal(mi[0], mi_repeated[1], "repeat: repeated first element")
614
615
616def test_tolist():
617    """Test tolist method"""
618    f_print_info("Testing tolist method...")
619
620    arrays = [['a', 'b'], ['one', 'two']]
slice_indexer (test_signature_phase14.py:177)
167    # Should accept axis
168    result = mi.repeat(2, axis=None)
169    assert result is not None, "repeat should return result"
170    print("  repeat: OK")
171
172
173def test_slice_indexer():
174    """Test slice_indexer has step parameter"""
175    mi = pandasCore.MultiIndex.from_tuples([('a', '1'), ('b', '2'), ('c', '3')], names=['x', 'y'])
176    # Should accept step
177    result = mi.slice_indexer(start=None, end=None, step=None)
178    assert result is not None, "slice_indexer should return result"
179    print("  slice_indexer: OK")
180
181
182def test_symmetric_difference():
183    """Test symmetric_difference has result_name and sort parameters"""
184    mi1 = pandasCore.MultiIndex.from_tuples([('a', '1'), ('b', '2')], names=['x', 'y'])
185    mi2 = pandasCore.MultiIndex.from_tuples([('a', '1'), ('c', '3')], names=['x', 'y'])
186    # Should accept result_name and sort
187    result = mi1.symmetric_difference(mi2, result_name=None, sort=None)
sortlevel (test_multiindex.py:286)
276    ctx.assert_true('first' in frame or 'level_0' in frame, "to_frame: has column")
277
278
279def test_sortlevel():
280    """Test sortlevel method"""
281    f_print_info("Testing sortlevel method...")
282
283    arrays = [['b', 'a', 'b', 'a'], ['two', 'one', 'one', 'two']]
284    mi = pandasCore.MultiIndex.from_arrays(arrays, names=['first', 'second'])
285
286    sorted_mi, indices = mi.sortlevel(0)
287    first_level_vals = sorted_mi.get_level_values(0)
288
289    # After sorting by level 0, 'a' values should come first
290    ctx.assert_equal('a', first_level_vals[0], "sortlevel: first value after sort")
291
292
293# =============================================================================
294# Statistics Methods Tests
295# =============================================================================