Skip to content

ENH Adds feature names support to dataframe protocol - #26464

Merged
ogrisel merged 24 commits into
scikit-learn:mainfrom
thomasjpfan:feature_names_dataframe_protocol
Jun 21, 2023
Merged

ogrisel merged 24 commits into
scikit-learn:mainfrom
thomasjpfan:feature_names_dataframe_protocol

Conversation

@thomasjpfan

Copy link
Copy Markdown
Member

Reference Issues/PRs

Towards #25896

What does this implement/fix? Explain your changes.

This PR allows all estimators to recognize the feature names from any DataFrame that follows the DataFrame interchange protocol. With this PR, DataFrames that support the interchange protocol and works with np.asarray will work with scikit-learn estimators.

@thomasjpfan

thomasjpfan commented May 30, 2023 •

Copy link
Copy Markdown
Member Author

I want to add this pyarrow test:

def test_check_feature_names_arrow():
    pa = importorskip("pyarrow")
    pd = importorskip("pandas")
    df = pd.DataFrame(
        {
            "n_legs": [None, 4, 5, None],
            "animals": ["Flamingo", "Horse", None, "Centipede"],
        },
        columns=["n_legs", "animals"],
    )
    table = pa.Table.from_pandas(df)

    table_names = _get_feature_names(table)
    assert_array_equal(table_names, df.columns)

but that adds a pyarrow dependency to our CI and pyarrow is quite a large dependency.

@ogrisel

ogrisel commented May 31, 2023 •

Copy link
Copy Markdown
Member

but that adds a pyarrow dependency to our CI and pyarrow is quite a large dependency.

I think it's ok to either add pyarrow or polars to one of our CI runs.

I think we would probably benefit from a real non-pandas dataframe integration test. But maybe this can come latter, once we implement generic dataframe support for cross-validation and meta-estimators (e.g. column transformer, pipeline, searchcv, bagging...).

@ogrisel ogrisel 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.

LGTM!

Comment thread sklearn/tests/test_base.py Outdated
Co-authored-by: Olivier Grisel <olivier.grisel@ensta.org>

@adrinjalali adrinjalali 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.

Same as @ogrisel I'd be happy to have a polars or some other dataframe lib included in the CI.

Comment thread sklearn/utils/validation.py Outdated

# extract feature names for support array containers
if hasattr(X, "columns"):
if hasattr(X, "columns") and hasattr(X, "iloc"):

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.

we REALLY need a _is_pandas_df util 🙈

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.

Yeah I think this would still catch other DataFrame libraries like Modin that have an iloc attribute as well, in which case might be better to have the __dataframe__ check first?

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.

I'm trying not to introduce a regression with pandas. Specifically df.__dataframe__ with the default allow_copy=True can make copies.

The better approach is use the DataFrame API SPEC. Concretely, DataFrame.get_column_names. Currently, there is no library that supports the SPEC yet.

There is an implementation of the DataFrame SPEC for pandas and polars: https://github.com/MarcoGorelli/impl-dataframe-api. The implementation for each library is one file each so it will not be hard for us to vendor and make use of the SPEC before the libraries adopt it.

As for this PR, I introduced a _is_pandas_df function that makes sure that X is a pandas DataFrame.

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.

+1 for temporarily vendoring the compat layer and try to only use the spec API in our estimators' code.

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.

The above can be done in a subsequent PR, no need to delay this one.

@adrinjalali

Copy link
Copy Markdown
Member

re:pyarrow, since pandas is thinking of making it a mandatory dependency anyway, I'd e happy to have it in one CI. But since it's large, rather not have it in every CI job.

@lorentzenchr lorentzenchr 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.

LGTM
As @adrinjalali says, some CI configurations with pyarrow or polars would be important, IMHO.

Comment thread doc/whats_new/v1.3.rst Outdated
Comment thread doc/whats_new/v1.3.rst Outdated
Comment thread doc/whats_new/v1.3.rst Outdated
Comment thread doc/whats_new/v1.3.rst Outdated

@ogrisel ogrisel 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.

The ridge failure seems unrelated, I will open a dedicated issue if none already exist.

Comment thread sklearn/utils/validation.py
Comment thread sklearn/tests/test_base.py Outdated
@github-actions

github-actions Bot commented Jun 21, 2023 •

Copy link
Copy Markdown

✔️ Linting Passed

All linting checks passed. Your pull request is in excellent shape! ☀️

Generated for commit: 9b3f26e

Comment thread sklearn/utils/_testing.py Outdated
Comment thread sklearn/utils/tests/test_validation.py

@glemaitre glemaitre 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.

Otherwise LGTM.

Comment thread sklearn/utils/validation.py
@ogrisel
ogrisel enabled auto-merge (squash) June 21, 2023 22:44
Comment thread sklearn/tests/test_base.py
@ogrisel
ogrisel merged commit 0e1f170 into scikit-learn:main Jun 21, 2023
REDVM pushed a commit to REDVM/scikit-learn that referenced this pull request Nov 16, 2023
)

Co-authored-by: Olivier Grisel <olivier.grisel@ensta.org>
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.

6 participants