Repository navigation
How should pandas-stubs balance typing precision, overload complexity, and runtime behavior for MultiIndex indexing? #71944
Replies: 3 comments 4 replies
|
A runtime edge case to include when evaluating an overload for a fully specified key: duplicate column labels can change the result. On pandas 3.0.3 I checked: import pandas as pd
cols = pd.MultiIndex.from_tuples([("A", "a"), ("A", "a")])
df = pd.DataFrame([[1, 2]], columns=cols)
print(type(df.loc[:, ("A", "a")]).__name__) # DataFrameSo even a complete tuple alone does not guarantee a Series unless uniqueness is also assumed. The duplicate-label guide discusses how duplicates affect dimensionality. A runtime/type-checker test matrix covering unique and duplicate full keys, partial keys, and slices could make the precision trade-off explicit. I can’t speak for the maintainers’ policy or planned direction. |
|
I think the best approach would be to prioritize precise type inference for the most common indexing patterns while keeping the overload definitions as simple and maintainable as possible. For MultiIndex operations, the main challenge is that Python's type system cannot always distinguish between a complete tuple key and a partial tuple key containing slices or other indexing expressions. A few ideas that could help: More specific overloads first: Handle common cases, such as fully specified MultiIndex keys returning a Series, before falling back to broader overloads. Personally, I believe the goal should be to provide accurate typing for common real-world usage without trying to model every possible runtime behavior of pandas perfectly. It would also be useful to establish consistent typing guidelines across APIs such as .loc, .iloc, MultiIndex, and GroupBy, so that future improvements follow the same principles. I'd be interested to hear how other contributors balance typing precision against long-term maintainability. |
|
One case I'd include in the tests for the overload is duplicate full column labels. On pandas 3.1.1, the exact same key returns a Series with unique labels and a DataFrame when the full label occurs twice. import pandas as pd
unique = pd.DataFrame(
[[1, 2]], columns=pd.MultiIndex.from_tuples([("A", "a"), ("A", "b")])
)
duplicate = pd.DataFrame(
[[1, 2]], columns=pd.MultiIndex.from_tuples([("A", "a"), ("A", "a")])
)
assert isinstance(unique.loc[:, ("A", "a")], pd.Series)
assert isinstance(duplicate.loc[:, ("A", "a")], pd.DataFrame)
assert isinstance(unique.loc[:, [("A", "a")]], pd.DataFrame)So even a fully specified tuple doesn't tell the checker how many columns match. I'd cover that case alongside the partial and slice keys before making the tuple overload more precise. The list-of-keys form is useful when the caller wants a DataFrame consistently. |
Uh oh!
There was an error while loading. Please reload this page.
Hi pandas maintainers and contributors!
While working on pandas-stubs issue #1018 (MultiIndex column selection with
.loc), I encountered an interesting challenge around overload resolution.A seemingly simple indexing expression can have different return types depending on whether the MultiIndex key is fully specified, partially specified, or contains slices.
For example:
This raises a broader design question:
How should we model pandas indexing APIs in static typing when the return type depends on the structure and completeness of an index key, especially when Python's type system cannot easily express exclusions between overlapping tuple types?
I'm particularly interested in the following:
.loc,.iloc, MultiIndex, and GroupBy?I'd love to understand the maintainers' perspective on the long-term direction of pandas-stubs typing.
Thanks for maintaining this amazing project!
All reactions