Talip7/scikit-learn-issues-multilabel huggingface dataset:
"sklearn.utils.estimator_checks.check_transformer_data_not_an_array" prompts error

### Describe the bug

the function sklearn.utils.estimator_checks.check_transformer_data_not_an_array is trying to apply X.tolist(), where X is a pd.DataFrame. This object has no method called "tolist" hence it prompts the following error:
AttributeError: 'DataFrame' object has no attribute 'tolist'
This makes the test function "check_estimator" pretty useless since tests can't be completed successfully.

### Steps/Code to Reproduce

```
import pytest
from sklearn.utils.estimator_checks import check_estimator
from sklearn.preprocessing import StandardScaler

def test_all_estimators():
    return check_estimator(StandardScaler())
```

### Expected Results

expected test to pass

### Actual Results

test fails due to - "AttributeError: 'DataFrame' object has no attribute 'tolist'"

### Versions

```shell
System:
    python: 3.10.8 | packaged by conda-forge | (main, Nov 22 2022, 08:16:33) [MSC v.1929 64 bit (AMD64)]
executable: C:\Users\tomer\anaconda3\envs\CorrActions\python.exe
   machine: Windows-10-10.0.22621-SP0
Python dependencies:
      sklearn: 1.2.1
          pip: 22.3.1
   setuptools: 65.6.3
        numpy: 1.23.0
        scipy: 1.9.3
       Cython: None
       pandas: 1.5.2
   matplotlib: 3.6.2
       joblib: 1.2.0
threadpoolctl: 3.1.0
Built with OpenMP: True
threadpoolctl info:
       user_api: blas
   internal_api: openblas
         prefix: libopenblas
       filepath: C:\Users\tomer\anaconda3\envs\CorrActions\Lib\site-packages\numpy\.libs\libopenblas.FB5AE2TYXYH2IJRDKGDGQ3XBKLKTF43H.gfortran-win_amd64.dll
        version: 0.3.20
threading_layer: pthreads
   architecture: Haswell
    num_threads: 8
       user_api: openmp
   internal_api: openmp
         prefix: vcomp
       filepath: C:\Users\tomer\anaconda3\envs\CorrActions\Lib\site-packages\sklearn\.libs\vcomp140.dll
        version: None
    num_threads: 8
       user_api: blas
   internal_api: mkl
         prefix: mkl_rt
       filepath: C:\Users\tomer\anaconda3\envs\CorrActions\Library\bin\mkl_rt.1.dll
        version: 2021.4-Product
threading_layer: intel
    num_threads: 4
```

COMMENT:
Are you setting `sklearn.set_config(transform_output="pandas")` ?

Labels: Bug, Needs Triage
"sklearn.utils.estimator_checks.check_transformer_data_not_an_array" prompts error

### Describe the bug

the function sklearn.utils.estimator_checks.check_transformer_data_not_an_array is trying to apply X.tolist(), where X is a pd.DataFrame. This object has no method called "tolist" hence it prompts the following error:
AttributeError: 'DataFrame' object has no attribute 'tolist'
This makes the test function "check_estimator" pretty useless since tests can't be completed successfully.

### Steps/Code to Reproduce

```
import pytest
from sklearn.utils.estimator_checks import check_estimator
from sklearn.preprocessing import StandardScaler

def test_all_estimators():
    return check_estimator(StandardScaler())
```

### Expected Results

expected test to pass

### Actual Results

test fails due to - "AttributeError: 'DataFrame' object has no attribute 'tolist'"

### Versions

```shell
System:
    python: 3.10.8 | packaged by conda-forge | (main, Nov 22 2022, 08:16:33) [MSC v.1929 64 bit (AMD64)]
executable: C:\Users\tomer\anaconda3\envs\CorrActions\python.exe
   machine: Windows-10-10.0.22621-SP0
Python dependencies:
      sklearn: 1.2.1
          pip: 22.3.1
   setuptools: 65.6.3
        numpy: 1.23.0
        scipy: 1.9.3
       Cython: None
       pandas: 1.5.2
   matplotlib: 3.6.2
       joblib: 1.2.0
threadpoolctl: 3.1.0
Built with OpenMP: True
threadpoolctl info:
       user_api: blas
   internal_api: openblas
         prefix: libopenblas
       filepath: C:\Users\tomer\anaconda3\envs\CorrActions\Lib\site-packages\numpy\.libs\libopenblas.FB5AE2TYXYH2IJRDKGDGQ3XBKLKTF43H.gfortran-win_amd64.dll
        version: 0.3.20
threading_layer: pthreads
   architecture: Haswell
    num_threads: 8
       user_api: openmp
   internal_api: openmp
         prefix: vcomp
       filepath: C:\Users\tomer\anaconda3\envs\CorrActions\Lib\site-packages\sklearn\.libs\vcomp140.dll
        version: None
    num_threads: 8
       user_api: blas
   internal_api: mkl
         prefix: mkl_rt
       filepath: C:\Users\tomer\anaconda3\envs\CorrActions\Library\bin\mkl_rt.1.dll
        version: 2021.4-Product
threading_layer: intel
    num_threads: 4
```

COMMENT:
You are using tolist incorrectly. You want: .values followed by tolist()

  type   tsneX      tsneY  
0  A      53.828863  20.740931  
1  B      57.816909  18.478468  
2  A      55.913429  22.948167  
3  C      56.603005  15.738954 
For the above dataframe, to get your X and Y values as a list you can do:

tsneY_data = df['tsneY'].values.tolist()
>> [20.740931, 18.478468, 22.948167, 15.7389541]

tsneX_data = df['tsneX'].values.tolist()
>> [53.828863, 57.816909, 55.913429, 56.603005]
As you have tried to set this to the column of a new dataframe, you can do:

new_data = pd.DataFrame()
new_data['tsneY'] = df['tsneY'].values.tolist()

> new_data
       tsneY
0  20.740931
1  18.478468
2  22.948167
3  15.738954

Labels: Bug, Needs Triage
"sklearn.utils.estimator_checks.check_transformer_data_not_an_array" prompts error

### Describe the bug

the function sklearn.utils.estimator_checks.check_transformer_data_not_an_array is trying to apply X.tolist(), where X is a pd.DataFrame. This object has no method called "tolist" hence it prompts the following error:
AttributeError: 'DataFrame' object has no attribute 'tolist'
This makes the test function "check_estimator" pretty useless since tests can't be completed successfully.

### Steps/Code to Reproduce

```
import pytest
from sklearn.utils.estimator_checks import check_estimator
from sklearn.preprocessing import StandardScaler

def test_all_estimators():
    return check_estimator(StandardScaler())
```

### Expected Results

expected test to pass

### Actual Results

test fails due to - "AttributeError: 'DataFrame' object has no attribute 'tolist'"

### Versions

```shell
System:
    python: 3.10.8 | packaged by conda-forge | (main, Nov 22 2022, 08:16:33) [MSC v.1929 64 bit (AMD64)]
executable: C:\Users\tomer\anaconda3\envs\CorrActions\python.exe
   machine: Windows-10-10.0.22621-SP0
Python dependencies:
      sklearn: 1.2.1
          pip: 22.3.1
   setuptools: 65.6.3
        numpy: 1.23.0
        scipy: 1.9.3
       Cython: None
       pandas: 1.5.2
   matplotlib: 3.6.2
       joblib: 1.2.0
threadpoolctl: 3.1.0
Built with OpenMP: True
threadpoolctl info:
       user_api: blas
   internal_api: openblas
         prefix: libopenblas
       filepath: C:\Users\tomer\anaconda3\envs\CorrActions\Lib\site-packages\numpy\.libs\libopenblas.FB5AE2TYXYH2IJRDKGDGQ3XBKLKTF43H.gfortran-win_amd64.dll
        version: 0.3.20
threading_layer: pthreads
   architecture: Haswell
    num_threads: 8
       user_api: openmp
   internal_api: openmp
         prefix: vcomp
       filepath: C:\Users\tomer\anaconda3\envs\CorrActions\Lib\site-packages\sklearn\.libs\vcomp140.dll
        version: None
    num_threads: 8
       user_api: blas
   internal_api: mkl
         prefix: mkl_rt
       filepath: C:\Users\tomer\anaconda3\envs\CorrActions\Library\bin\mkl_rt.1.dll
        version: 2021.4-Product
threading_layer: intel
    num_threads: 4
```

COMMENT:
as @jeremiedbb mentioned, I am setting `sklearn.set_config(transform_output="pandas")`  and this is what causes the error to prompt, setting `sklearn.set_config(transform_output="default")` results in the test to pass as expected.

Is this the desired behavior?

Labels: Bug, Needs Triage
"sklearn.utils.estimator_checks.check_transformer_data_not_an_array" prompts error

### Describe the bug

the function sklearn.utils.estimator_checks.check_transformer_data_not_an_array is trying to apply X.tolist(), where X is a pd.DataFrame. This object has no method called "tolist" hence it prompts the following error:
AttributeError: 'DataFrame' object has no attribute 'tolist'
This makes the test function "check_estimator" pretty useless since tests can't be completed successfully.

### Steps/Code to Reproduce

```
import pytest
from sklearn.utils.estimator_checks import check_estimator
from sklearn.preprocessing import StandardScaler

def test_all_estimators():
    return check_estimator(StandardScaler())
```

### Expected Results

expected test to pass

### Actual Results

test fails due to - "AttributeError: 'DataFrame' object has no attribute 'tolist'"

### Versions

```shell
System:
    python: 3.10.8 | packaged by conda-forge | (main, Nov 22 2022, 08:16:33) [MSC v.1929 64 bit (AMD64)]
executable: C:\Users\tomer\anaconda3\envs\CorrActions\python.exe
   machine: Windows-10-10.0.22621-SP0
Python dependencies:
      sklearn: 1.2.1
          pip: 22.3.1
   setuptools: 65.6.3
        numpy: 1.23.0
        scipy: 1.9.3
       Cython: None
       pandas: 1.5.2
   matplotlib: 3.6.2
       joblib: 1.2.0
threadpoolctl: 3.1.0
Built with OpenMP: True
threadpoolctl info:
       user_api: blas
   internal_api: openblas
         prefix: libopenblas
       filepath: C:\Users\tomer\anaconda3\envs\CorrActions\Lib\site-packages\numpy\.libs\libopenblas.FB5AE2TYXYH2IJRDKGDGQ3XBKLKTF43H.gfortran-win_amd64.dll
        version: 0.3.20
threading_layer: pthreads
   architecture: Haswell
    num_threads: 8
       user_api: openmp
   internal_api: openmp
         prefix: vcomp
       filepath: C:\Users\tomer\anaconda3\envs\CorrActions\Lib\site-packages\sklearn\.libs\vcomp140.dll
        version: None
    num_threads: 8
       user_api: blas
   internal_api: mkl
         prefix: mkl_rt
       filepath: C:\Users\tomer\anaconda3\envs\CorrActions\Library\bin\mkl_rt.1.dll
        version: 2021.4-Product
threading_layer: intel
    num_threads: 4
```

COMMENT:
> Is this the desired behavior?

Yes, these checks applied to scikit-learn estimators are meant to be used with the default global config.

Labels: Bug, Needs Triage
Implement class that removes features with NaNs in sklearn.feature_selection module

### Describe the workflow you want to enable

Currently, there seems to be no way in Sklearn to remove features with NaNs (only to impute missing values). As the number of NaNs increases, imputation becomes less trustworthy, so I implemented my own class to remove features with a large number of NaNs. The inspiration for this were the drug variables from the Human Connectome project. Many of the 1200 subjects simply did not take any hard drugs, so we have a large number of NaNs in the those variables. 

### Describe your proposed solution

Implement a new class in `sklearn.feature_selection`. Something like:

```python
class NaNRemover(SelectorMixin,BaseEstimator):
    '''Feature selector that removes all features with missing values
    greater than provided threshold'''
    
    def __init__(self,threshold=0.1):
        self.threshold = threshold
        
    def fit(self,X,y=None):
        
        X = self._validate_data(
            X,
            accept_sparse=("csr","csc"),
            dtype=np.float64,
            force_all_finite="allow-nan"
            )
        
        n_samples = X.shape[0]
        
        self.threshold = round(self.threshold * n_samples)
        self.nans_per_feature = np.count_nonzero(np.isnan(X),axis=0)
        
        return self
    
    def _get_support_mask(self):
        return self.nans_per_feature < self.threshold
    
    def _more_tags(self):
        return {"allow_nan": True}
```

With the default value, this will drop all features where 10% of the samples have NaNs (thus becoming more 'liberal' with increasing `threshold`, i.e. allowing more rows to have NaNs. E.g. a `threshold=1.0` would only drop features, were all samples have NaNs (thus having a similar logic as `VarianceThreshold`, because all values are the same). Of course one could also think about implementing it with the opposite logic (lower threshold --> more liberal).

### Describe alternatives you've considered, if relevant

_No response_

### Additional context

_No response_

COMMENT:
Thank you for the feature request! @JohannesWiesner As for scikit-learn's [inclusion criteria](https://scikit-learn.org/stable/faq.html#what-are-the-inclusion-criteria-for-new-algorithms), may you share references or papers that study this method of removing features?

@GaelVaroquaux What do you think about this feature request?

Labels: New Feature, Needs Decision - Include Feature
Implement class that removes features with NaNs in sklearn.feature_selection module

### Describe the workflow you want to enable

Currently, there seems to be no way in Sklearn to remove features with NaNs (only to impute missing values). As the number of NaNs increases, imputation becomes less trustworthy, so I implemented my own class to remove features with a large number of NaNs. The inspiration for this were the drug variables from the Human Connectome project. Many of the 1200 subjects simply did not take any hard drugs, so we have a large number of NaNs in the those variables. 

### Describe your proposed solution

Implement a new class in `sklearn.feature_selection`. Something like:

```python
class NaNRemover(SelectorMixin,BaseEstimator):
    '''Feature selector that removes all features with missing values
    greater than provided threshold'''
    
    def __init__(self,threshold=0.1):
        self.threshold = threshold
        
    def fit(self,X,y=None):
        
        X = self._validate_data(
            X,
            accept_sparse=("csr","csc"),
            dtype=np.float64,
            force_all_finite="allow-nan"
            )
        
        n_samples = X.shape[0]
        
        self.threshold = round(self.threshold * n_samples)
        self.nans_per_feature = np.count_nonzero(np.isnan(X),axis=0)
        
        return self
    
    def _get_support_mask(self):
        return self.nans_per_feature < self.threshold
    
    def _more_tags(self):
        return {"allow_nan": True}
```

With the default value, this will drop all features where 10% of the samples have NaNs (thus becoming more 'liberal' with increasing `threshold`, i.e. allowing more rows to have NaNs. E.g. a `threshold=1.0` would only drop features, were all samples have NaNs (thus having a similar logic as `VarianceThreshold`, because all values are the same). Of course one could also think about implementing it with the opposite logic (lower threshold --> more liberal).

### Describe alternatives you've considered, if relevant

_No response_

### Additional context

_No response_

COMMENT:
@thomasjpfan: Didn't know of the inclusion criteria. I can definitely provide some papers that used this method, but I don't know if there are any papers that have **studied** it.

Labels: New Feature, Needs Decision - Include Feature
Implement class that removes features with NaNs in sklearn.feature_selection module

### Describe the workflow you want to enable

Currently, there seems to be no way in Sklearn to remove features with NaNs (only to impute missing values). As the number of NaNs increases, imputation becomes less trustworthy, so I implemented my own class to remove features with a large number of NaNs. The inspiration for this were the drug variables from the Human Connectome project. Many of the 1200 subjects simply did not take any hard drugs, so we have a large number of NaNs in the those variables. 

### Describe your proposed solution

Implement a new class in `sklearn.feature_selection`. Something like:

```python
class NaNRemover(SelectorMixin,BaseEstimator):
    '''Feature selector that removes all features with missing values
    greater than provided threshold'''
    
    def __init__(self,threshold=0.1):
        self.threshold = threshold
        
    def fit(self,X,y=None):
        
        X = self._validate_data(
            X,
            accept_sparse=("csr","csc"),
            dtype=np.float64,
            force_all_finite="allow-nan"
            )
        
        n_samples = X.shape[0]
        
        self.threshold = round(self.threshold * n_samples)
        self.nans_per_feature = np.count_nonzero(np.isnan(X),axis=0)
        
        return self
    
    def _get_support_mask(self):
        return self.nans_per_feature < self.threshold
    
    def _more_tags(self):
        return {"allow_nan": True}
```

With the default value, this will drop all features where 10% of the samples have NaNs (thus becoming more 'liberal' with increasing `threshold`, i.e. allowing more rows to have NaNs. E.g. a `threshold=1.0` would only drop features, were all samples have NaNs (thus having a similar logic as `VarianceThreshold`, because all values are the same). Of course one could also think about implementing it with the opposite logic (lower threshold --> more liberal).

### Describe alternatives you've considered, if relevant

_No response_

### Additional context

_No response_

COMMENT:
I kinda feel like this must be somewhere in scikit-lego, but can't find it here (https://scikit-lego.netlify.app/api/preprocessing.html)

cc @koaning

I don't think for such transformers we need the same inclusion criteria. But this seems quite tricky. It's very easy for the output of this transformer to be an empty array. Deploying this in production where you routinely re-train can be very risky.

Labels: New Feature, Needs Decision - Include Feature
Implement class that removes features with NaNs in sklearn.feature_selection module

### Describe the workflow you want to enable

Currently, there seems to be no way in Sklearn to remove features with NaNs (only to impute missing values). As the number of NaNs increases, imputation becomes less trustworthy, so I implemented my own class to remove features with a large number of NaNs. The inspiration for this were the drug variables from the Human Connectome project. Many of the 1200 subjects simply did not take any hard drugs, so we have a large number of NaNs in the those variables. 

### Describe your proposed solution

Implement a new class in `sklearn.feature_selection`. Something like:

```python
class NaNRemover(SelectorMixin,BaseEstimator):
    '''Feature selector that removes all features with missing values
    greater than provided threshold'''
    
    def __init__(self,threshold=0.1):
        self.threshold = threshold
        
    def fit(self,X,y=None):
        
        X = self._validate_data(
            X,
            accept_sparse=("csr","csc"),
            dtype=np.float64,
            force_all_finite="allow-nan"
            )
        
        n_samples = X.shape[0]
        
        self.threshold = round(self.threshold * n_samples)
        self.nans_per_feature = np.count_nonzero(np.isnan(X),axis=0)
        
        return self
    
    def _get_support_mask(self):
        return self.nans_per_feature < self.threshold
    
    def _more_tags(self):
        return {"allow_nan": True}
```

With the default value, this will drop all features where 10% of the samples have NaNs (thus becoming more 'liberal' with increasing `threshold`, i.e. allowing more rows to have NaNs. E.g. a `threshold=1.0` would only drop features, were all samples have NaNs (thus having a similar logic as `VarianceThreshold`, because all values are the same). Of course one could also think about implementing it with the opposite logic (lower threshold --> more liberal).

### Describe alternatives you've considered, if relevant

_No response_

### Additional context

_No response_

COMMENT:
> @GaelVaroquaux What do you think about this feature request?

Removing features with a very large fraction of missing values can be relevant. We do that sometimes in situations where we get a huge fraction of missing values (we remove with thresholds much larger than .1).

However, I never do that in a pipeline: I want to know which feature I am removing, and I want to control it so that it is constant.

In a way, my comment echos that of Adrin on deploying this in production.

I'm not sure that I would push this feature.

Labels: New Feature, Needs Decision - Include Feature
Implement class that removes features with NaNs in sklearn.feature_selection module

### Describe the workflow you want to enable

Currently, there seems to be no way in Sklearn to remove features with NaNs (only to impute missing values). As the number of NaNs increases, imputation becomes less trustworthy, so I implemented my own class to remove features with a large number of NaNs. The inspiration for this were the drug variables from the Human Connectome project. Many of the 1200 subjects simply did not take any hard drugs, so we have a large number of NaNs in the those variables. 

### Describe your proposed solution

Implement a new class in `sklearn.feature_selection`. Something like:

```python
class NaNRemover(SelectorMixin,BaseEstimator):
    '''Feature selector that removes all features with missing values
    greater than provided threshold'''
    
    def __init__(self,threshold=0.1):
        self.threshold = threshold
        
    def fit(self,X,y=None):
        
        X = self._validate_data(
            X,
            accept_sparse=("csr","csc"),
            dtype=np.float64,
            force_all_finite="allow-nan"
            )
        
        n_samples = X.shape[0]
        
        self.threshold = round(self.threshold * n_samples)
        self.nans_per_feature = np.count_nonzero(np.isnan(X),axis=0)
        
        return self
    
    def _get_support_mask(self):
        return self.nans_per_feature < self.threshold
    
    def _more_tags(self):
        return {"allow_nan": True}
```

With the default value, this will drop all features where 10% of the samples have NaNs (thus becoming more 'liberal' with increasing `threshold`, i.e. allowing more rows to have NaNs. E.g. a `threshold=1.0` would only drop features, were all samples have NaNs (thus having a similar logic as `VarianceThreshold`, because all values are the same). Of course one could also think about implementing it with the opposite logic (lower threshold --> more liberal).

### Describe alternatives you've considered, if relevant

_No response_

### Additional context

_No response_

COMMENT:
@adrinjalali It does sound more like something that could live in scikit-lego than in scikit-learn, yeah.

EDIT: 

Actually, on second thought, I think I'd need a compelling case to support this. Would you _really_ want to handle this automatically? Feels much safer as a manual thing you'd do as part of your data exploration.

That suggests that this might be more of a candidate for a pandas-pipeline library to be used as a function in `.pipe()`-lines.

Labels: New Feature, Needs Decision - Include Feature