Skip to content

Conversation

Chiwendaiyue
Copy link

@Chiwendaiyue Chiwendaiyue commented Oct 7, 2025

  1. What does this PR do?

Adds insert_level method to MultiIndex for inserting new levels at specified positions.

  1. Motivation

This addresses the feature request in issue #62558 for a simple way to add levels to MultiIndex at given positions.

  1. Key changes
  • Implement insert_level method in pandas/core/indexes/multi.py
  • Add comprehensive test suite in pandas/tests/indexes/multi/test_insert_level.py
  • Handle various edge cases and error conditions
  1. Testing
  • All new tests pass
  • Existing functionality remains unchanged
  • Handles scalar values and array-like inputs
  • Proper error handling for invalid inputs
  1. Example usage

idx = pd.MultiIndex.from_tuples([('A', 1), ('B', 2)])
result = idx.insert_level(1, 'new_level')

cloudboat added 2 commits October 7, 2025 20:43
- Implement insert_level method for MultiIndex to insert new levels at specified positions
- Add comprehensive test cases for the new functionality
- Fix level names handling to match expected behavior

Resolves: MultiIndex level insertion feature request
- Implement insert_level method for MultiIndex to insert new levels at specified positions
- Add comprehensive test cases for the new functionality
- Fix level names handling to match expected behavior

Resolves: MultiIndex level insertion feature request
@Chiwendaiyue Chiwendaiyue marked this pull request as draft October 7, 2025 13:05
@Chiwendaiyue Chiwendaiyue marked this pull request as ready for review October 7, 2025 13:18
@Chiwendaiyue Chiwendaiyue changed the title multiindex-insert-level ENH: Implement MultiIndex.insert_level for inserting levels at specified positions Oct 7, 2025
@Chiwendaiyue Chiwendaiyue marked this pull request as draft October 7, 2025 13:29
cloudboat added 4 commits October 7, 2025 21:57
- Implement insert_level method for MultiIndex to insert new levels at specified positions
- Add comprehensive test cases for the new functionality
- Fix level names handling to match expected behavior

Resolves: MultiIndex level insertion feature request
@Chiwendaiyue Chiwendaiyue marked this pull request as ready for review October 7, 2025 15:49
Copy link
Member

@Alvaro-Kothe Alvaro-Kothe left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the PR. Here are some suggestions against the test suite.

It seems that you committed fastparquet and pyarrow accidentally.

Also, can you add an entry to whatsnew?

Comment on lines +8 to +12
def setup_method(self):
self.simple_idx = pd.MultiIndex.from_tuples(
[("A", 1), ("B", 2), ("C", 3)], names=["level1", "level2"]
)
self.empty_idx = pd.MultiIndex.from_tuples([], names=["level1", "level2"])
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

NIT: I would prefer that you define this in the test body that should use it.

)
self.empty_idx = pd.MultiIndex.from_tuples([], names=["level1", "level2"])

def test_insert_level_basic(self):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you parametrize this test?

result = self.simple_idx.insert_level(0, "new_val", name="new_level")
assert result.names[0] == "new_level"

def test_insert_level_edge_positions(self):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This can go into the first test.

result_end = self.simple_idx.insert_level(2, "end")
assert result_end.nlevels == 3

def test_insert_level_error_cases(self):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you parametrize this?

with pytest.raises(ValueError, match="Length of values must match"):
self.simple_idx.insert_level(1, ["too", "few"])

def test_insert_level_with_different_data_types(self):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These tests could go into the first test too.

Comment on lines +78 to +91
def test_debug_names():
idx = pd.MultiIndex.from_tuples(
[("A", 1), ("B", 2), ("C", 3)], names=["level1", "level2"]
)
print("Original names:", idx.names)

result = idx.insert_level(0, "new_value")
print("Result names:", result.names)

expected = pd.MultiIndex.from_tuples(
[("new_value", "A", 1), ("new_value", "B", 2), ("new_value", "C", 3)],
names=[None, "level1", "level2"],
)
print("Expected names:", expected.names)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why does this exist?


tm.assert_index_equal(original, self.simple_idx)

assert result.nlevels == original.nlevels + 1
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This assertion feels redundant against the first test.

Comment on lines +38 to +40
def test_insert_level_with_name(self):
result = self.simple_idx.insert_level(0, "new_val", name="new_level")
assert result.names[0] == "new_level"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You could also test adding names in the first test and remove this test.

Co-authored-by: Álvaro Kothe <kothe65@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants