Skip to content

GH-46179: [Python] Bump index level once if pandas df already contains __index_level_i__ column - #46884

Merged
raulcd merged 3 commits into
apache:mainfrom
AlenkaF:gh-46179-duplicates-index-levels
Jun 15, 2026
Merged

GH-46179: [Python] Bump index level once if pandas df already contains __index_level_i__ column#46884
raulcd merged 3 commits into
apache:mainfrom
AlenkaF:gh-46179-duplicates-index-levels

Conversation

@AlenkaF

@AlenkaF AlenkaF commented Jun 23, 2025

Copy link
Copy Markdown
Member

Rationale for this change

PyArrow adds a __inex_level_i__ column to the PyArrow table if the pandas dataframe has an unnamed index it wants to preserve. Currently that creates a duplicate, if such a column already exists.

What changes are included in this PR?

Bumping the integer number in the generated column in order to not get any duplicates.

Are these changes tested?

Yes.

Are there any user-facing changes?

No.

@github-actions

Copy link
Copy Markdown

⚠️ GitHub issue #46179 has been automatically assigned in GitHub to PR creator.

@AlenkaF AlenkaF changed the title GH-46179: Bump index level once if pandas df already contains __index_level_i__ column GH-46179: [Python] Bump index level once if pandas df already contains __index_level_i__ column Jun 23, 2025
@AlenkaF
AlenkaF force-pushed the gh-46179-duplicates-index-levels branch from c915159 to 3ee4599 Compare May 25, 2026 14:34
Copilot AI review requested due to automatic review settings May 25, 2026 14:34

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

This PR addresses GH-46179 in PyArrow’s pandas conversion by avoiding duplicate Arrow field names when a pandas DataFrame already contains __index_level_i__ columns, ensuring generated index columns use a non-conflicting name.

Changes:

  • Update generated index column naming to pick the next available __index_level_{j}__ name if the default collides with existing columns.
  • Ensure uniqueness across both DataFrame columns and previously generated index columns when multiple index levels are serialized.
  • Add regression tests for single-index and MultiIndex cases where __index_level_0__ already exists as a DataFrame column.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.

File Description
python/pyarrow/pandas_compat.py Adjusts index-level name generation to avoid collisions with existing column names and previously assigned index column names.
python/pyarrow/tests/test_pandas.py Updates existing metadata assertion and adds new regression tests validating the bumped index column names.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +381 to +384
j = i
while f'__index_level_{j:d}__' in column_names:
j += 1
return f'__index_level_{j:d}__'

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Isn't schema based conversion already buggy without this change when it comes to the index levels? It probably silently ignores the duplicated level 0 currently?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

OK, getting used to this :) Copilot can't answer. Well, I think the change suggested can be a possible follow-up if we see this would be needed. But I do not think it is in the scope of this PR.

@github-actions github-actions Bot added awaiting committer review Awaiting committer review and removed awaiting review Awaiting review labels May 26, 2026
@AlenkaF
AlenkaF marked this pull request as ready for review May 26, 2026 09:28
@AlenkaF
AlenkaF requested review from raulcd and rok as code owners May 26, 2026 09:28
@AlenkaF

AlenkaF commented May 26, 2026

Copy link
Copy Markdown
Member Author

@jorisvandenbossche what do you think of the proposed change in this PR?

@AlenkaF

AlenkaF commented Jun 8, 2026

Copy link
Copy Markdown
Member Author

cc @raulcd if you have some time for review. No rush!

@raulcd raulcd left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

To be fair I don't know much about the __index_level_{i} works.
Can we add an explicit test to validate the index is respected?

Based on the issue snippet:

In [40]: df = pd.DataFrame({"col": [1, 2, 3], "__index_level_0__": [1, 2, 3]}, index=[2, 3, 4])

In [41]: df
Out[41]: 
   col  __index_level_0__
2    1                  1
3    2                  2
4    3                  3

In [42]: pa.table(df)
Out[42]: 
pyarrow.Table
col: int64
__index_level_0__: int64
__index_level_0__: int64
----
col: [[1,2,3]]
__index_level_0__: [[1,2,3]]
__index_level_0__: [[2,3,4]]

I would expect the pa.table(df).to_pandas() to continue presenting the index correctly:

>> pa.table(df).to_pandas()
   col  __index_level_0__
2    1                  1
3    2                  2
4    3                  3

Can we validate the pandas index is the new __index_level_1__ instead of the column __index_level_0__?

@github-actions github-actions Bot added awaiting changes Awaiting changes and removed awaiting committer review Awaiting committer review labels Jun 8, 2026
@github-actions github-actions Bot added awaiting change review Awaiting change review and removed awaiting changes Awaiting changes labels Jun 11, 2026
@AlenkaF

AlenkaF commented Jun 11, 2026

Copy link
Copy Markdown
Member Author

Thanks for the review @raulcd!
I have added an explicit test: c5f1770. Is this what you has in mind?

@AlenkaF

AlenkaF commented Jun 11, 2026

Copy link
Copy Markdown
Member Author

Dev failure does not seem to be connected to the changes in this PR.

Comment thread python/pyarrow/tests/test_pandas.py
@github-actions github-actions Bot added awaiting merge Awaiting merge and removed awaiting change review Awaiting change review labels Jun 12, 2026
@raulcd
raulcd merged commit a81e6c6 into apache:main Jun 15, 2026
19 of 20 checks passed
@raulcd raulcd removed the awaiting merge Awaiting merge label Jun 15, 2026
@conbench-apache-arrow

Copy link
Copy Markdown

After merging your PR, Conbench analyzed the 4 benchmarking runs that have been run so far on merge-commit a81e6c6.

There were no benchmark performance regressions. 🎉

The full Conbench report has more details. It also includes information about 2 possible false positives for unstable benchmarks that are known to sometimes produce them.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants