Talip7/scikit-learn-issues-multilabel huggingface dataset:
DBSCAN always triggers and EfficiencyWarning

### Describe the bug

Calling dbscan always triggers an efficiency warning. There is no apparent way to either call it correctly or disable the warning. 

This was originally reported as an issue in SemiBin, which uses DBSCAN under the hood: https://github.com/BigDataBiology/SemiBin/issues/175

### Steps/Code to Reproduce

```python
import numpy as np
from sklearn.cluster import dbscan
from sklearn.neighbors import kneighbors_graph, sort_graph_by_row_values

f = np.random.randn(10_000, 240)
dist_matrix = kneighbors_graph(
    f,
    n_neighbors=200,
    mode='distance',
    p=2,
    n_jobs=3)

_, labels = dbscan(dist_matrix,
        eps=0.1, min_samples=5, n_jobs=4, metric='precomputed')


dist_matrix = sort_graph_by_row_values(dist_matrix)
_, labels = dbscan(dist_matrix,
        eps=0.1, min_samples=5, n_jobs=4, metric='precomputed')
```

### Expected Results

No warning, at least in second call

### Actual Results

```
/home/luispedro/.mambaforge/envs/py3.11/lib/python3.11/site-packages/sklearn/neighbors/_base.py:248: EfficiencyWarning: Precomputed sparse input was not sorted by row values. Use the function sklearn.neighbors.sort_graph_by_row_values to sort the input by row values, with warn_when_not_sorted=False to remove this warning.
  warnings.warn(
/home/luispedro/.mambaforge/envs/py3.11/lib/python3.11/site-packages/sklearn/neighbors/_base.py:248: EfficiencyWarning: Precomputed sparse input was not sorted by row values. Use the function sklearn.neighbors.sort_graph_by_row_values to sort the input by row values, with warn_when_not_sorted=False to remove this warning.
  warnings.warn(
```

### Versions

```shell
I tested on the current main branch, 5cdbbf15e3fade7cc2462ef66dc4ea0f37f390e3, but it has been going on for a while (see original SemiBin report from September 2024):


System:
    python: 3.11.9 | packaged by conda-forge | (main, Apr 19 2024, 18:36:13) [GCC 12.3.0]
executable: /home/luispedro/.mambaforge/envs/py3.11/bin/python3.11
   machine: Linux-6.8.0-55-generic-x86_64-with-glibc2.39

Python dependencies:
      sklearn: 1.7.dev0
          pip: 24.0
   setuptools: 70.0.0
        numpy: 1.26.4
        scipy: 1.13.1
       Cython: None
       pandas: 2.2.2
   matplotlib: 3.8.4
       joblib: 1.4.2
threadpoolctl: 3.5.0

Built with OpenMP: True

threadpoolctl info:
       user_api: blas
   internal_api: openblas
    num_threads: 16
         prefix: libopenblas
       filepath: /home/luispedro/.mambaforge/envs/py3.11/lib/libopenblasp-r0.3.27.so
        version: 0.3.27
threading_layer: pthreads
   architecture: Haswell

       user_api: openmp
   internal_api: openmp
    num_threads: 16
         prefix: libgomp
       filepath: /home/luispedro/.mambaforge/envs/py3.11/lib/libgomp.so.1.0.0
        version: None
```

COMMENT:
From an initial look, it seems both solutions fix the warning but I would be inclined to choose your second proposal @Luis-Varona since the first just seems like a quick fix (which could potentially be inefficient). Could you explain what exactly it is doing?

Labels: Bug, help wanted, Needs Investigation
⚠️ CI failed on Check sdist (last failure: Mar 20, 2025) ⚠️

**CI is still failing on [Check sdist](https://github.com/scikit-learn/scikit-learn/actions/runs/13959330746)** (Mar 20, 2025)

COMMENT:
Need to bump from 3.9 to 3.10 here:
https://github.com/scikit-learn/scikit-learn/blob/5cdbbf15e3fade7cc2462ef66dc4ea0f37f390e3/.github/workflows/check-sdist.yml#L19

Labels: Needs Triage
Allow column names to pass through when fitting `narwhals` dataframes

### Describe the workflow you want to enable

Currently when fitting with a `narwhals` DataFrame, the feature names do not pass through because it does not implement a `__dataframe__` method.

Example:

```python
import narwhals as nw
import pandas as pd
import polars as pl
from sklearn.preprocessing import StandardScaler

df_pd = pd.DataFrame({"a": [0, 1, 2], "b": [3, 4, 5]})
df_pl = pl.DataFrame(df_pd)
df_nw = nw.from_native(df_pd)

s_pd, s_pl, s_nw = StandardScaler(), StandardScaler(), StandardScaler()
s_pd.fit(df_pd)
s_pl.fit(df_pl)
s_nw.fit(df_nw)

print(s_pd.feature_names_in_)
print(s_pl.feature_names_in_)
print(s_nw.feature_names_in_)
```

**Expected output**

```
['a' 'b']
['a' 'b']
['a' 'b']
```

**Actual output**
```
['a' 'b']
['a' 'b']
AttributeError: 'StandardScaler' object has no attribute 'feature_names_in_'
```

All other attributes on `s_nw` are what I'd expect.

### Describe your proposed solution

This should be easy enough to implement by adding another check within `sklearn.utils.validation._get_feature_names`:

1. Add `_is_narwhals_df` method, borrowing logic from [`_is_pandas_df`](https://github.com/scikit-learn/scikit-learn/blob/main/sklearn/utils/validation.py#L2343)

```python
def _is_narwhals_df(X):
    """Return True if the X is a narwhals dataframe."""
    try:
        nw = sys.modules["narwhals"]
    except KeyError:
        return False
    return isinstance(X, nw.DataFrame)
```

2. Add an additional check to [`_get_feature_names`](https://github.com/scikit-learn/scikit-learn/blob/main/sklearn/utils/validation.py#L2393-L2408):

```python
    elif _is_narwhals_df(X):
        feature_names = np.asarray(X.columns, dtype=object)
```

### Describe alternatives you've considered, if relevant

_No response_

### Additional context

https://github.com/narwhals-dev/narwhals/issues/355#issuecomment-2734066008

COMMENT:
Thanks @ryansheabla for opening the request, and Stefanie for your reply! 🙏 

> I think narwhals is to be used internally by libraries and users then could reliably pass polars, pandas or pyarrow frames.

True, but I think here @ryansheabla is making a library which internally uses Narwhals and would like to pass that around.

Also, although Narwhals supports PyArrow tables, scikit-learn doesn't https://github.com/scikit-learn/scikit-learn/issues/25896#issuecomment-2740201980

Even though Narwhals was originally designed with tool builders in mind, I've anecdotally been hearing from users working with it directly as a friendly and unified interface to different engines

I don't think it would be too much of a lift to generalise the Polars code in scikit-learn to also handle Narwhals input, given that the API is very similar. Happy to work towards this if you'd be open to it! 🙌

Labels: New Feature, Needs Triage
Allow column names to pass through when fitting `narwhals` dataframes

### Describe the workflow you want to enable

Currently when fitting with a `narwhals` DataFrame, the feature names do not pass through because it does not implement a `__dataframe__` method.

Example:

```python
import narwhals as nw
import pandas as pd
import polars as pl
from sklearn.preprocessing import StandardScaler

df_pd = pd.DataFrame({"a": [0, 1, 2], "b": [3, 4, 5]})
df_pl = pl.DataFrame(df_pd)
df_nw = nw.from_native(df_pd)

s_pd, s_pl, s_nw = StandardScaler(), StandardScaler(), StandardScaler()
s_pd.fit(df_pd)
s_pl.fit(df_pl)
s_nw.fit(df_nw)

print(s_pd.feature_names_in_)
print(s_pl.feature_names_in_)
print(s_nw.feature_names_in_)
```

**Expected output**

```
['a' 'b']
['a' 'b']
['a' 'b']
```

**Actual output**
```
['a' 'b']
['a' 'b']
AttributeError: 'StandardScaler' object has no attribute 'feature_names_in_'
```

All other attributes on `s_nw` are what I'd expect.

### Describe your proposed solution

This should be easy enough to implement by adding another check within `sklearn.utils.validation._get_feature_names`:

1. Add `_is_narwhals_df` method, borrowing logic from [`_is_pandas_df`](https://github.com/scikit-learn/scikit-learn/blob/main/sklearn/utils/validation.py#L2343)

```python
def _is_narwhals_df(X):
    """Return True if the X is a narwhals dataframe."""
    try:
        nw = sys.modules["narwhals"]
    except KeyError:
        return False
    return isinstance(X, nw.DataFrame)
```

2. Add an additional check to [`_get_feature_names`](https://github.com/scikit-learn/scikit-learn/blob/main/sklearn/utils/validation.py#L2393-L2408):

```python
    elif _is_narwhals_df(X):
        feature_names = np.asarray(X.columns, dtype=object)
```

### Describe alternatives you've considered, if relevant

_No response_

### Additional context

https://github.com/narwhals-dev/narwhals/issues/355#issuecomment-2734066008

COMMENT:
From what I can tell scikit-learn does not have a problem converting narwhals DataFrames to numpy arrays, given my provided example runs except for the `AttributeError`.  Stepping through the fit methods, it seems to follow the same path through `check_array` as both pandas (1.5.3) and polars (1.24.0) and has no problem converting to numpy datatypes (though I wouldn't be surprised if there might be other issues on more a more complex example).

I added the changes to the code I outlined above in my virtual environment and the code runs as expected. You can even pass pandas/polars frames to the narwhals-fitted scaler and vice-versa. I'd be willing to open a PR but this feels like it's part of a larger discussion, especially if there's a possibility of a).

Labels: New Feature, Needs Triage
Allow column names to pass through when fitting `narwhals` dataframes

### Describe the workflow you want to enable

Currently when fitting with a `narwhals` DataFrame, the feature names do not pass through because it does not implement a `__dataframe__` method.

Example:

```python
import narwhals as nw
import pandas as pd
import polars as pl
from sklearn.preprocessing import StandardScaler

df_pd = pd.DataFrame({"a": [0, 1, 2], "b": [3, 4, 5]})
df_pl = pl.DataFrame(df_pd)
df_nw = nw.from_native(df_pd)

s_pd, s_pl, s_nw = StandardScaler(), StandardScaler(), StandardScaler()
s_pd.fit(df_pd)
s_pl.fit(df_pl)
s_nw.fit(df_nw)

print(s_pd.feature_names_in_)
print(s_pl.feature_names_in_)
print(s_nw.feature_names_in_)
```

**Expected output**

```
['a' 'b']
['a' 'b']
['a' 'b']
```

**Actual output**
```
['a' 'b']
['a' 'b']
AttributeError: 'StandardScaler' object has no attribute 'feature_names_in_'
```

All other attributes on `s_nw` are what I'd expect.

### Describe your proposed solution

This should be easy enough to implement by adding another check within `sklearn.utils.validation._get_feature_names`:

1. Add `_is_narwhals_df` method, borrowing logic from [`_is_pandas_df`](https://github.com/scikit-learn/scikit-learn/blob/main/sklearn/utils/validation.py#L2343)

```python
def _is_narwhals_df(X):
    """Return True if the X is a narwhals dataframe."""
    try:
        nw = sys.modules["narwhals"]
    except KeyError:
        return False
    return isinstance(X, nw.DataFrame)
```

2. Add an additional check to [`_get_feature_names`](https://github.com/scikit-learn/scikit-learn/blob/main/sklearn/utils/validation.py#L2393-L2408):

```python
    elif _is_narwhals_df(X):
        feature_names = np.asarray(X.columns, dtype=object)
```

### Describe alternatives you've considered, if relevant

_No response_

### Additional context

https://github.com/narwhals-dev/narwhals/issues/355#issuecomment-2734066008

COMMENT:
Closing as a duplicate for https://github.com/scikit-learn/scikit-learn/issues/31049 and https://github.com/scikit-learn/scikit-learn/issues/25896

Labels: New Feature, Needs Triage
RFC Make all conditional/optional attributes raise a meaningful error when missing

Related: https://github.com/scikit-learn/scikit-learn/issues/10525, https://github.com/scikit-learn/scikit-learn/issues/30999

Right now accessing attributes which are added to the instances when a method is called (like `coef_` in `fit`) before they're created, raises a simple python `AttributeError`. This is not only on our estimators, but also sometimes on other objects such as display objects.

Since we've had issues / confusions before, I was wondering if we'd want to introduce meaningful error messages when somebody tries to access an attribute which is not there yet, and we can tell them why it's not there. Like, `Call fit to have this attribute` or `set store_cv_results=True to have this attribute.`

In terms of UX, that to me is a very clear improvement, but I'm not sure if we want to add the complexity. We can certainly find ways to make it easier to implement via some python magic, to reduce/minimise the boilerplate code.

cc @scikit-learn/core-devs

COMMENT:
+1 for the UX improvement. But I need to see a sketch of an implementation first (to estimate complexity) for a final vote.

Labels: API, RFC
RFC Make all conditional/optional attributes raise a meaningful error when missing

Related: https://github.com/scikit-learn/scikit-learn/issues/10525, https://github.com/scikit-learn/scikit-learn/issues/30999

Right now accessing attributes which are added to the instances when a method is called (like `coef_` in `fit`) before they're created, raises a simple python `AttributeError`. This is not only on our estimators, but also sometimes on other objects such as display objects.

Since we've had issues / confusions before, I was wondering if we'd want to introduce meaningful error messages when somebody tries to access an attribute which is not there yet, and we can tell them why it's not there. Like, `Call fit to have this attribute` or `set store_cv_results=True to have this attribute.`

In terms of UX, that to me is a very clear improvement, but I'm not sure if we want to add the complexity. We can certainly find ways to make it easier to implement via some python magic, to reduce/minimise the boilerplate code.

cc @scikit-learn/core-devs

COMMENT:
I opened https://github.com/scikit-learn/scikit-learn/pull/31066 as a proof of concept.

Labels: API, RFC
RFC Make all conditional/optional attributes raise a meaningful error when missing

Related: https://github.com/scikit-learn/scikit-learn/issues/10525, https://github.com/scikit-learn/scikit-learn/issues/30999

Right now accessing attributes which are added to the instances when a method is called (like `coef_` in `fit`) before they're created, raises a simple python `AttributeError`. This is not only on our estimators, but also sometimes on other objects such as display objects.

Since we've had issues / confusions before, I was wondering if we'd want to introduce meaningful error messages when somebody tries to access an attribute which is not there yet, and we can tell them why it's not there. Like, `Call fit to have this attribute` or `set store_cv_results=True to have this attribute.`

In terms of UX, that to me is a very clear improvement, but I'm not sure if we want to add the complexity. We can certainly find ways to make it easier to implement via some python magic, to reduce/minimise the boilerplate code.

cc @scikit-learn/core-devs

COMMENT:
> I opened [#31066](https://github.com/scikit-learn/scikit-learn/pull/31066) as a proof of concept.

Would this be boilerplate that needs to get added to every estimator? It seems the con would be a lot of code complexity.

If "fit" and "store_cv_results" are the only ways to get a fitted `attribute_`,  another option could be simply error out anytime `attribute_` is accessed, but not defined with a more generic message, but still more helpful?

```
attribute_ was accessed. Call fit to fit this attribute, or store_cv_results to 
```

Labels: API, RFC
RFC Make all conditional/optional attributes raise a meaningful error when missing

Related: https://github.com/scikit-learn/scikit-learn/issues/10525, https://github.com/scikit-learn/scikit-learn/issues/30999

Right now accessing attributes which are added to the instances when a method is called (like `coef_` in `fit`) before they're created, raises a simple python `AttributeError`. This is not only on our estimators, but also sometimes on other objects such as display objects.

Since we've had issues / confusions before, I was wondering if we'd want to introduce meaningful error messages when somebody tries to access an attribute which is not there yet, and we can tell them why it's not there. Like, `Call fit to have this attribute` or `set store_cv_results=True to have this attribute.`

In terms of UX, that to me is a very clear improvement, but I'm not sure if we want to add the complexity. We can certainly find ways to make it easier to implement via some python magic, to reduce/minimise the boilerplate code.

cc @scikit-learn/core-devs

COMMENT:
There are paths to get fitted attributes that depend on parameters. For example, `HistGradientBoostingRegressor.validation_score_` is only defined if there is early stopping.

I guess we can have a generic `attribute_ was accessed. Call fit...` in the `BaseEstimator`, but then have a `FittedAttribute` construct for the more specific cases, like `cv_results_` or `validation_score_`.

Labels: API, RFC
RFC Make all conditional/optional attributes raise a meaningful error when missing

Related: https://github.com/scikit-learn/scikit-learn/issues/10525, https://github.com/scikit-learn/scikit-learn/issues/30999

Right now accessing attributes which are added to the instances when a method is called (like `coef_` in `fit`) before they're created, raises a simple python `AttributeError`. This is not only on our estimators, but also sometimes on other objects such as display objects.

Since we've had issues / confusions before, I was wondering if we'd want to introduce meaningful error messages when somebody tries to access an attribute which is not there yet, and we can tell them why it's not there. Like, `Call fit to have this attribute` or `set store_cv_results=True to have this attribute.`

In terms of UX, that to me is a very clear improvement, but I'm not sure if we want to add the complexity. We can certainly find ways to make it easier to implement via some python magic, to reduce/minimise the boilerplate code.

cc @scikit-learn/core-devs

COMMENT:
So far it seems like there are two cases that need handling:
1. attributes that don't exist yet, because `fit` hasn't been called
2. attributes that don't exist because the estimator is not configured to produce it

Is there a third scenario?

I'm unsure how much complexity we should add to solve this. In particular category (1) is not super interesting in my mind, the answer to that is to read/find out the generic "fitted attributes only exist after `fit` has been called" and then you are done. Attributes in group (2) are more tricky and I can see people spending a lot of time/frustration trying to work out why an attribute doesn't exist (presumably because they think the set the hyper-parameter to the correct value, but something subtle went wrong).

Labels: API, RFC
RFC Make all conditional/optional attributes raise a meaningful error when missing

Related: https://github.com/scikit-learn/scikit-learn/issues/10525, https://github.com/scikit-learn/scikit-learn/issues/30999

Right now accessing attributes which are added to the instances when a method is called (like `coef_` in `fit`) before they're created, raises a simple python `AttributeError`. This is not only on our estimators, but also sometimes on other objects such as display objects.

Since we've had issues / confusions before, I was wondering if we'd want to introduce meaningful error messages when somebody tries to access an attribute which is not there yet, and we can tell them why it's not there. Like, `Call fit to have this attribute` or `set store_cv_results=True to have this attribute.`

In terms of UX, that to me is a very clear improvement, but I'm not sure if we want to add the complexity. We can certainly find ways to make it easier to implement via some python magic, to reduce/minimise the boilerplate code.

cc @scikit-learn/core-devs

COMMENT:
A problem I have had is that it is currently not possible to inspect an estimator to find out all its (possible) fitted attributes without fitting it. If we define that list we can have a generic implementation in `BaseEstimator` that raises different exceptions based on the name of the attribute

Labels: API, RFC
RFC Make all conditional/optional attributes raise a meaningful error when missing

Related: https://github.com/scikit-learn/scikit-learn/issues/10525, https://github.com/scikit-learn/scikit-learn/issues/30999

Right now accessing attributes which are added to the instances when a method is called (like `coef_` in `fit`) before they're created, raises a simple python `AttributeError`. This is not only on our estimators, but also sometimes on other objects such as display objects.

Since we've had issues / confusions before, I was wondering if we'd want to introduce meaningful error messages when somebody tries to access an attribute which is not there yet, and we can tell them why it's not there. Like, `Call fit to have this attribute` or `set store_cv_results=True to have this attribute.`

In terms of UX, that to me is a very clear improvement, but I'm not sure if we want to add the complexity. We can certainly find ways to make it easier to implement via some python magic, to reduce/minimise the boilerplate code.

cc @scikit-learn/core-devs

COMMENT:
I'm hesitant with this. To me it is more a documentation issue.

The fact that all documented attributes (i.e those with a trailing underscore) are attributes that are only available after some computations have been done by the object is something that does not confuse users, at least when said objects are estimators. We can improve doc for non estimator objects like displays. But since it's a general pattern I think it's enough to document the pattern in one place.

Regarding conditional attributes, the linked issue is 7 years old and at the time they were poorly documented but since then their documentation has been improved a lot and as far as I know all such attribute document in which condition they are available. For instance `cv_results_` in RidgeCV: `only available if store_cv_results=True and cv=None`. So again I'm not sure it really confuses users nowadays. Maybe we could make it more visible in the docstring, like under some sphinx directive, but to me it shoudl be enough.

Labels: API, RFC
RFC Make all conditional/optional attributes raise a meaningful error when missing

Related: https://github.com/scikit-learn/scikit-learn/issues/10525, https://github.com/scikit-learn/scikit-learn/issues/30999

Right now accessing attributes which are added to the instances when a method is called (like `coef_` in `fit`) before they're created, raises a simple python `AttributeError`. This is not only on our estimators, but also sometimes on other objects such as display objects.

Since we've had issues / confusions before, I was wondering if we'd want to introduce meaningful error messages when somebody tries to access an attribute which is not there yet, and we can tell them why it's not there. Like, `Call fit to have this attribute` or `set store_cv_results=True to have this attribute.`

In terms of UX, that to me is a very clear improvement, but I'm not sure if we want to add the complexity. We can certainly find ways to make it easier to implement via some python magic, to reduce/minimise the boilerplate code.

cc @scikit-learn/core-devs

COMMENT:
> A problem I have had is that it is currently not possible to inspect an estimator to find out all its (possible) fitted attributes without fitting it

@betatim technically you can :)
```py
from sklearn.linear_model import RidgeCV
import inspect
from numpydoc.docscrape import NumpyDocString

doc = NumpyDocString(inspect.getdoc(RidgeCV))

[attr.name for attr in doc["Attributes"]]
```

Labels: API, RFC
load_iris documentation target_names name wrong type

### Describe the issue linked to the documentation

In the documentation of load_iris (https://scikit-learn.org/stable/modules/generated/sklearn.datasets.load_iris.html) the type of target_names is list but in code it's a numpyarray.

**Version Checked**
Version: 1.6.1

### Suggest a potential alternative/fix

Hello i'm new to the opensource world so this would be my first issue raised.

There would be two way to fix it : either change the documentation to reflect the type of the data or change the data to type to be in line with the feature_names and the documentation (a list)

COMMENT:
I would like to raise a PR for this! Please let me know if I can do so.

Labels: Documentation