Question: Current implementation of cannot be used to compare sets The current implementation of yields incorrect results when used to compare sets. Consider the following self-explanatory code comparing two (equal as by ) sets: Although the two sets are obviously the same, the last equality check using approx is failing. A quick view into the implementation of makes it obvious why this is the case: In , only is used (in ), but since sets are unordered, so is the resulting iterator. This means, for sets such an implementation cannot work. What makes things worse is the confusion that seems to exist here between the different abstract base classes: In the method, clearly is mentioned, explicitly. However, a set is not a sequence type, but only a collection type (because of the missing order). It is, however, iterable and since this is the only thing that is actually checked in the implementation, the code seems to work for sets, where, in fact, it does not. As a first step, I would suggest one could keep the current implementation, but explicitly check for sequence types (i.e. classes having a method) and delete all mentions of in the code as well as on the documentation page and make it crystal clear that there is only an implementation for sequence types. But what would be way better would, of course, be an implementation for arbitrary container comparisons. Tested with pytest version 7.0.1.

>>> np.array([0.1, 0.2]) + np.array([0.2, 0.1]) == approx(0.3) # doctest: +SKIP         True <ins>    Only ordered sequences are supported, because ``approx`` needs    to infer the relative position of the sequences without ambiguity. This means    ``sets`` and other unordered sequences are not supported.    Finally, dictionary *values* can also be compared::        >>> {'a': 0.1 + 0.2, 'b': 0.2 + 0.4} == approx({'a': 0.3, 'b': 0.6})        True    The comparision will be true if both mappings have the same keys and their    respective values match the expected tolerances.    **Tolerances**</ins>     By default, ``approx`` considers numbers within a relative tolerance of     ``1e-6`` (i.e. one part in a million) of its expected value to be equal.     This treatment would lead to surprising results if the expected value was


Question: Current implementation of cannot be used to compare sets The current implementation of yields incorrect results when used to compare sets. Consider the following self-explanatory code comparing two (equal as by ) sets: Although the two sets are obviously the same, the last equality check using approx is failing. A quick view into the implementation of makes it obvious why this is the case: In , only is used (in ), but since sets are unordered, so is the resulting iterator. This means, for sets such an implementation cannot work. What makes things worse is the confusion that seems to exist here between the different abstract base classes: In the method, clearly is mentioned, explicitly. However, a set is not a sequence type, but only a collection type (because of the missing order). It is, however, iterable and since this is the only thing that is actually checked in the implementation, the code seems to work for sets, where, in fact, it does not. As a first step, I would suggest one could keep the current implementation, but explicitly check for sequence types (i.e. classes having a method) and delete all mentions of in the code as well as on the documentation page and make it crystal clear that there is only an implementation for sequence types. But what would be way better would, of course, be an implementation for arbitrary container comparisons. Tested with pytest version 7.0.1.

expected = _as_numpy_array(expected)         cls = ApproxNumpy     elif (        isinstance(expected, Iterable)        hasattr(expected, "__getitem__")         and isinstance(expected, Sized)         # Type ignored because the error is wrong -- not unreachable.         and not isinstance(expected, STRING_TYPES)  # type: ignore[unreachable]     ):        cls = ApproxSequencelike        cls = ApproxSequenceLike    elif (        isinstance(expected, Collection)        # Type ignored because the error is wrong -- not unreachable.        and not isinstance(expected, STRING_TYPES)  # type: ignore[unreachable]    ):        msg = f"pytest.approx() only supports ordered sequences, but got: {repr(expected)}"        raise TypeError(msg)     else:         cls = ApproxScalar


Question: Version 7.1.0 seems like not picking up Over SciPy we have started to see the message in the title in our Azure Pipelines which started picking up 7.1.0 instead of 7.0.1 lastn ight. From the deprecation and removal list we couldn't see which item might have caused it. One speculation we might generate is that our mark is not registered in our file explicitly and maybe registrations are now obligatory. Here is a complete SciPy test suite example with all installation steps provided. And our file lives here Thank you for all the efforts.

"""         if self._confcutdir is None:             return True        try:            path.relative_to(self._confcutdir)        except ValueError:            return False        return True        return path not in self._confcutdir.parents      def _try_load_conftest(         self, anchor: Path, importmode: Union[str, ImportMode], rootpath: Path


Question: ModuleNotFoundError for Numpy when fails <!-- Thanks for submitting an issue! Quick check-list while reporting bugs: --When using to compare lists in a test, a is raised for Numpy whenever the test fails. If the test succeeds, there is no such error. It appears that does not require Numpy to run, but the error message requires Numpy to display the details. Since does not require Numpy to function correctly, it should not require Numpy to display the error. macOS Big Sur Version 11.6.2 No which makes the whole error message confusing and leads you to believe it failed because Numpy is not installed instead of the fact it was an assertion error.

def _repr_compare(self, other_side: Sequence[float]) -> List[str]:         import math<del>        import numpy as np</del>          if len(self.expected) != len(other_side):             return [


Question: ModuleNotFoundError for Numpy when fails <!-- Thanks for submitting an issue! Quick check-list while reporting bugs: --When using to compare lists in a test, a is raised for Numpy whenever the test fails. If the test succeeds, there is no such error. It appears that does not require Numpy to run, but the error message requires Numpy to display the details. Since does not require Numpy to function correctly, it should not require Numpy to display the error. macOS Big Sur Version 11.6.2 No which makes the whole error message confusing and leads you to believe it failed because Numpy is not installed instead of the fact it was an assertion error.

abs_diff = abs(approx_value.expected - other_value)                 max_abs_diff = max(max_abs_diff, abs_diff)                 if other_value == 0.0:                    max_rel_diff = np.inf                    max_rel_diff = math.inf                 else:                     max_rel_diff = max(max_rel_diff, abs_diff / abs(other_value))                 different_ids.append(i)


Question: Improved error when (empty tuple) is passed to or When using as a context manager, you can pass an exception type or tuple of exception types; it's then an error if no exception is raised or if the exception raised is not an instance of the expected type(s). The same logic applies to , which has a near-identical API. The problem is that if you pass the empty tuple , this will always result in an error: even if an exception is raised, it can't be an instance of ! I think we should explicitly check tuple inputs, and raise a more helpful error message if they're empty. For example: "Passing is an error, because it's impossible to raise an exception which is not an instance of any type. Raising exceptions is already understood as failing the test, so you don't need any special code to say 'this should never raise an exception'." (for bonus points, should have the same message, with instead of ) The same logic, and same error message, applies to the argument to . "Passing is an error, because it's impossible to emit a warning which is not an instance of any type. To assert that no warnings are emitted, use <whatever we come up with for

"""     __tracebackhide__ = True <ins>    if not expected_exception:        raise ValueError(            f"Expected an exception type or a tuple of exception types, but got `{expected_exception!r}`. "            f"Raising exceptions is already understood as failing the test, so you don't need "            f"any special code to say 'this should never raise an exception'."        )</ins>     if isinstance(expected_exception, type):         excepted_exceptions: Tuple[Type[E], ...] = (expected_exception,)     else:


Question: Test functions that return non-None should raise a warning/error Consider this test: Did you spot the error? The second parametrization has a typo, is 9, not 8. But this test actually doesn't test anything, because it returns the assertion rather than asserting it. This is a common enough mistake, and it wouldn't normally be a problem except that it can silently cause false positives in test suites. I propose that test functions that return anything except None fail with a message that cues users that they probably meant to assert rather than return. This feature could be disabled (or enabled, if there are backwards-compatibility issues) via a config flag if necessary.

from _pytest.pathlib import visit from _pytest.scope import Scope from _pytest.warning_types import PytestCollectionWarningfrom _pytest.warning_types import PytestReturnNotNoneWarning from _pytest.warning_types import PytestUnhandledCoroutineWarning  if TYPE_CHECKING:     from typing_extensions import Literal     from _pytest.scope import _ScopeName


Question: Test functions that return non-None should raise a warning/error Consider this test: Did you spot the error? The second parametrization has a typo, is 9, not 8. But this test actually doesn't test anything, because it returns the assertion rather than asserting it. This is a common enough mistake, and it wouldn't normally be a problem except that it can silently cause false positives in test suites. I propose that test functions that return anything except None fail with a message that cues users that they probably meant to assert rather than return. This feature could be disabled (or enabled, if there are backwards-compatibility issues) via a config flag if necessary.

result = testfunction(**testargs)     if hasattr(result, "__await__") or hasattr(result, "__aiter__"):         async_warn_and_skip(pyfuncitem.nodeid)    elif result is not None:        warnings.warn(            PytestReturnNotNoneWarning(                f"Expected None, but {pyfuncitem.nodeid} returned {result!r}, which will be an error in a "                "future version of pytest.  Did you mean to use `assert` instead of `return`?"            )        )     return True  diff --git a/src/_pytest/warning_types.py b/src/_pytest/warning_types.py-- a/src/_pytest/warning_types.py++ b/src/_pytest/warning_types.py


Question: Test functions that return non-None should raise a warning/error Consider this test: Did you spot the error? The second parametrization has a typo, is 9, not 8. But this test actually doesn't test anything, because it returns the assertion rather than asserting it. This is a common enough mistake, and it wouldn't normally be a problem except that it can silently cause false positives in test suites. I propose that test functions that return anything except None fail with a message that cues users that they probably meant to assert rather than return. This feature could be disabled (or enabled, if there are backwards-compatibility issues) via a config flag if necessary.

__module__ = "pytest"  @finalclass PytestReturnNotNoneWarning(PytestDeprecationWarning):    """Warning emitted when a test function is returning value other than None."""    __module__ = "pytest" @final class PytestExperimentalApiWarning(PytestWarning, FutureWarning):     """Warning category used to denote experiments in pytest.diff --git a/src/pytest/__init__.py b/src/pytest/__init__.py-- a/src/pytest/__init__.py++ b/src/pytest/__init__.py


Question: Test functions that return non-None should raise a warning/error Consider this test: Did you spot the error? The second parametrization has a typo, is 9, not 8. But this test actually doesn't test anything, because it returns the assertion rather than asserting it. This is a common enough mistake, and it wouldn't normally be a problem except that it can silently cause false positives in test suites. I propose that test functions that return anything except None fail with a message that cues users that they probably meant to assert rather than return. This feature could be disabled (or enabled, if there are backwards-compatibility issues) via a config flag if necessary.

from _pytest.warning_types import PytestDeprecationWarning from _pytest.warning_types import PytestExperimentalApiWarning from _pytest.warning_types import PytestRemovedIn8Warning<ins>from _pytest.warning_types import PytestReturnNotNoneWarning</ins> from _pytest.warning_types import PytestUnhandledCoroutineWarning from _pytest.warning_types import PytestUnhandledThreadExceptionWarning from _pytest.warning_types import PytestUnknownMarkWarning


Question: Test functions that return non-None should raise a warning/error Consider this test: Did you spot the error? The second parametrization has a typo, is 9, not 8. But this test actually doesn't test anything, because it returns the assertion rather than asserting it. This is a common enough mistake, and it wouldn't normally be a problem except that it can silently cause false positives in test suites. I propose that test functions that return anything except None fail with a message that cues users that they probably meant to assert rather than return. This feature could be disabled (or enabled, if there are backwards-compatibility issues) via a config flag if necessary.

"PytestDeprecationWarning",     "PytestExperimentalApiWarning",     "PytestRemovedIn8Warning",<ins>    "PytestReturnNotNoneWarning",</ins>     "Pytester",     "PytestPluginManager",     "PytestUnhandledCoroutineWarning",


Question: add getfeaturenames to CategoricalEncoder We should add a ` to the new CategoricalEncoder, as discussed . I think it would be good to be consistent with the PolynomialFeature which allows passing in original feature names to map them to new feature names. Also see .

>>> enc.inverse_transform([[0, 1, 1, 0, 0], [0, 0, 0, 1, 0]])     array([['Male', 1],            [None, 2]], dtype=object)<ins>    >>> enc.get_feature_names()    array(['x0_Female', 'x0_Male', 'x1_1', 'x1_2', 'x1_3'], dtype=object)</ins>      See also     --------


Question: add getfeaturenames to CategoricalEncoder We should add a ` to the new CategoricalEncoder, as discussed . I think it would be good to be consistent with the PolynomialFeature which allows passing in original feature names to map them to new feature names. Also see .

return X_tr <ins>    def get_feature_names(self, input_features=None):        """Return feature names for output features.        Parameters        ----------        input_features : list of string, length n_features, optional            String names for input features if available. By default,            "x0", "x1", ... "xn_features" is used.        Returns        -------        output_feature_names : array of string, length n_output_features        """        check_is_fitted(self, 'categories_')        cats = self.categories_        if input_features is None:            input_features = ['x%d' % i for i in range(len(cats))]        elif(len(input_features) != len(self.categories_)):            raise ValueError(                "input_features should have length equal to number of "                "features ({}), got {}".format(len(self.categories_),                                               len(input_features)))        feature_names = []        for i in range(len(cats)):            names = [                input_features[i] + '_' + six.text_type(t) for t in cats[i]]            feature_names.extend(names)        return np.array(feature_names, dtype=object)</ins>  class OrdinalEncoder(_BaseEncoder):     """Encode categorical features as an integer array.


Question: linearmodel.RidgeClassifierCV's Parameter storecvvalues issue Parameter storecvvalues error on sklearn.linearmodel.RidgeClassifierCV import numpy as np from sklearn import linearmodel as lm #test database n = 100 x = (n, 30) y = (size = n) rr = lm.RidgeClassifierCV(alphas = (0.1, 1000, 0.1), normalize = True, storecvvalues = True).fit(x, y) Expected to get the usual ridge regression model output, keeping the cross validation predictions as attribute. TypeError: init() got an unexpected keyword argument 'storecvvalues' lm.RidgeClassifierCV actually has no parameter storecvvalues, even though some attributes depends on it. Windows-10-10.0.-SP0 Python 3.6.3 (default, Oct 15 2017, 03:27:45) [MSC v.1900 64 bit (AMD64)] NumPy 1.13.3 SciPy 0.19.1 Scikit-Learn 0.19.1 Add storecvvalues boolean flag support to RidgeClassifierCV Add storecvvalues support to RidgeClassifierCV - documentation claims that usage of this flag is possible: While actually usage of this flag gives

store_cv_values : boolean, default=False         Flag indicating if the cross-validation values corresponding to        each alpha should be stored in the `cv_values_` attribute (see        below). This flag is only compatible with `cv=None` (i.e. using        each alpha should be stored in the ``cv_values_`` attribute (see        below). This flag is only compatible with ``cv=None`` (i.e. using         Generalized Cross-Validation).      Attributes     ----------     cv_values_ : array, shape = [n_samples, n_alphas] or \         shape = [n_samples, n_targets, n_alphas], optional        Cross-validation values for each alpha (if `store_cv_values=True` and \        `cv=None`). After `fit()` has been called, this attribute will \        contain the mean squared errors (by default) or the values of the \        `{loss,score}_func` function (if provided in the constructor).        Cross-validation values for each alpha (if ``store_cv_values=True``\        and ``cv=None``). After ``fit()`` has been called, this attribute \        will contain the mean squared errors (by default) or the values \        of the ``{loss,score}_func`` function (if provided in the constructor).      coef_ : array, shape = [n_features] or [n_targets, n_features]         Weight vector(s).


Question: linearmodel.RidgeClassifierCV's Parameter storecvvalues issue Parameter storecvvalues error on sklearn.linearmodel.RidgeClassifierCV import numpy as np from sklearn import linearmodel as lm #test database n = 100 x = (n, 30) y = (size = n) rr = lm.RidgeClassifierCV(alphas = (0.1, 1000, 0.1), normalize = True, storecvvalues = True).fit(x, y) Expected to get the usual ridge regression model output, keeping the cross validation predictions as attribute. TypeError: init() got an unexpected keyword argument 'storecvvalues' lm.RidgeClassifierCV actually has no parameter storecvvalues, even though some attributes depends on it. Windows-10-10.0.-SP0 Python 3.6.3 (default, Oct 15 2017, 03:27:45) [MSC v.1900 64 bit (AMD64)] NumPy 1.13.3 SciPy 0.19.1 Scikit-Learn 0.19.1 Add storecvvalues boolean flag support to RidgeClassifierCV Add storecvvalues support to RidgeClassifierCV - documentation claims that usage of this flag is possible: While actually usage of this flag gives

weights inversely proportional to class frequencies in the input data         as ``n_samples / (n_classes * np.bincount(y))``     store_cv_values : boolean, default=False        Flag indicating if the cross-validation values corresponding to        each alpha should be stored in the ``cv_values_`` attribute (see        below). This flag is only compatible with ``cv=None`` (i.e. using        Generalized Cross-Validation).     Attributes     ----------    cv_values_ : array, shape = [n_samples, n_alphas] or \    shape = [n_samples, n_responses, n_alphas], optional        Cross-validation values for each alpha (if `store_cv_values=True` and    `cv=None`). After `fit()` has been called, this attribute will contain \    the mean squared errors (by default) or the values of the \    `{loss,score}_func` function (if provided in the constructor).    cv_values_ : array, shape = [n_samples, n_targets, n_alphas], optional        Cross-validation values for each alpha (if ``store_cv_values=True`` and        ``cv=None``). After ``fit()`` has been called, this attribute will        contain the mean squared errors (by default) or the values of the        ``{loss,score}_func`` function (if provided in the constructor).      coef_ : array, shape = [n_features] or [n_targets, n_features]         Weight vector(s).


Question: linearmodel.RidgeClassifierCV's Parameter storecvvalues issue Parameter storecvvalues error on sklearn.linearmodel.RidgeClassifierCV import numpy as np from sklearn import linearmodel as lm #test database n = 100 x = (n, 30) y = (size = n) rr = lm.RidgeClassifierCV(alphas = (0.1, 1000, 0.1), normalize = True, storecvvalues = True).fit(x, y) Expected to get the usual ridge regression model output, keeping the cross validation predictions as attribute. TypeError: init() got an unexpected keyword argument 'storecvvalues' lm.RidgeClassifierCV actually has no parameter storecvvalues, even though some attributes depends on it. Windows-10-10.0.-SP0 Python 3.6.3 (default, Oct 15 2017, 03:27:45) [MSC v.1900 64 bit (AMD64)] NumPy 1.13.3 SciPy 0.19.1 Scikit-Learn 0.19.1 Add storecvvalues boolean flag support to RidgeClassifierCV Add storecvvalues support to RidgeClassifierCV - documentation claims that usage of this flag is possible: While actually usage of this flag gives

advantage of the multi-variate response support in Ridge.     """     def __init__(self, alphas=(0.1, 1.0, 10.0), fit_intercept=True,                 normalize=False, scoring=None, cv=None, class_weight=None):                 normalize=False, scoring=None, cv=None, class_weight=None,                 store_cv_values=False):         super(RidgeClassifierCV, self).__init__(             alphas=alphas, fit_intercept=fit_intercept, normalize=normalize,            scoring=scoring, cv=cv)            scoring=scoring, cv=cv, store_cv_values=store_cv_values)         self.class_weight = class_weight      def fit(self, X, y, sample_weight=None):


Question: BUG Inconsistent f1score behavior when combining label indicator input with labels attribute When using label indicator inputs for ypred and ytrue, metrics.f1score calculates the macro average over all label-specific f-scores whenever the labels parameter includes column index 0. It should only average over the label-specific scores indicated by the labels parameter, as it does when 0 is not present in the labels parameter. <!-- Instructions For Filing a Bug: --<!-- Please paste or specifically describe the actual output or traceback. --Windows-7-6.1.7601-SP1 Python 3.5.3 (default, May 15 2017, 10:43:23) [MSC v.1900 64 bit (AMD64)] NumPy 1.13.1 SciPy 0.19.0 Scikit-Learn 0.19.0 <!-- Thanks for contributing! --

raise ValueError('All labels must be in [0, n labels). '                                  'Got %d < 0' % np.min(labels)) <ins>        if n_labels is not None:</ins>             y_true = y_true[:, labels[:n_labels]]             y_pred = y_pred[:, labels[:n_labels]]


Question: TfidfVectorizer dtype argument ignored TfidfVectorizer's fit/fittransform output is always np.float64 instead of the specified dtype FitFailedWarning raised by cross validation could do with better message Current message says "Classifier fit failed" but the estimator is not necessarily a classifier. (Perhaps that's too pedantic of me...) is not technically the best way to display an error message. We could either use and include the whole traceback; or we can use to print it properly (though I think this is the same as ). Another thing we can consider, now that provides structured results to and , is to store the full traceback in some array of .

...         pass     ...     print(repr(w[-1].message))     ... # doctest: +NORMALIZE_WHITESPACE    FitFailedWarning("Classifier fit failed. The score on this train-test    partition for these parameters will be set to 0.000000. Details:    \\nValueError('Penalty term must be positive; got (C=-2)',)",)    FitFailedWarning('Estimator fit failed. The score on this train-test    partition for these parameters will be set to 0.000000.    Details: \\nValueError: Penalty term must be positive; got (C=-2)\\n',)      .. versionchanged:: 0.18        Moved from sklearn.cross_validation.diff --git a/sklearn/model_selection/_validation.py b/sklearn/model_selection/_validation.py-- a/sklearn/model_selection/_validation.py++ b/sklearn/model_selection/_validation.py


Question: TfidfVectorizer dtype argument ignored TfidfVectorizer's fit/fittransform output is always np.float64 instead of the specified dtype FitFailedWarning raised by cross validation could do with better message Current message says "Classifier fit failed" but the estimator is not necessarily a classifier. (Perhaps that's too pedantic of me...) is not technically the best way to display an error message. We could either use and include the whole traceback; or we can use to print it properly (though I think this is the same as ). Another thing we can consider, now that provides structured results to and , is to store the full traceback in some array of .

import warnings import numbers import time<ins>from traceback import format_exception_only</ins>  import numpy as np import scipy.sparse as sp


Question: TfidfVectorizer dtype argument ignored TfidfVectorizer's fit/fittransform output is always np.float64 instead of the specified dtype FitFailedWarning raised by cross validation could do with better message Current message says "Classifier fit failed" but the estimator is not necessarily a classifier. (Perhaps that's too pedantic of me...) is not technically the best way to display an error message. We could either use and include the whole traceback; or we can use to print it properly (though I think this is the same as ). Another thing we can consider, now that provides structured results to and , is to store the full traceback in some array of .

test_scores = error_score                 if return_train_score:                     train_scores = error_score            warnings.warn("Classifier fit failed. The score on this train-test"            warnings.warn("Estimator fit failed. The score on this train-test"                           " partition for these parameters will be set to %f. "                          "Details: \n%r" % (error_score, e), FitFailedWarning)                          "Details: \n%s" %                          (error_score, format_exception_only(type(e), e)[0]),                          FitFailedWarning)         else:             raise ValueError("error_score must be the string 'raise' or a"                              " numeric value. (Hint: if using 'raise', please"


Question: integers in RidgeCV alpha making one of the alphas a float fixes the problem. This should be handled internally. Python3.6 integers in RidgeCV alpha making one of the alphas a float fixes the problem. This should be handled internally. Python3.6

a one-versus-all approach. Concretely, this is implemented by taking     advantage of the multi-variate response support in Ridge.     """<ins></ins>     def __init__(self, alpha=1.0, fit_intercept=True, normalize=False,                  copy_X=True, max_iter=None, tol=1e-3, class_weight=None,                  solver="auto", random_state=None):


Question: integers in RidgeCV alpha making one of the alphas a float fixes the problem. This should be handled internally. Python3.6 integers in RidgeCV alpha making one of the alphas a float fixes the problem. This should be handled internally. Python3.6

scorer = check_scoring(self, scoring=self.scoring, allow_none=True)         error = scorer is None         if np.any(self.alphas < 0):            raise ValueError("alphas cannot be negative. "                             "Got {} containing some "                             "negative value instead.".format(self.alphas))         for i, alpha in enumerate(self.alphas):             if error:                out, c = _errors(alpha, y, v, Q, QT_y)                out, c = _errors(float(alpha), y, v, Q, QT_y)             else:                out, c = _values(alpha, y, v, Q, QT_y)                out, c = _values(float(alpha), y, v, Q, QT_y)             cv_values[:, i] = out.ravel()             C.append(c)


Question: integers in RidgeCV alpha making one of the alphas a float fixes the problem. This should be handled internally. Python3.6 integers in RidgeCV alpha making one of the alphas a float fixes the problem. This should be handled internally. Python3.6

fit_intercept=True, normalize=False, scoring=None,                  cv=None, gcv_mode=None,                  store_cv_values=False):        self.alphas = alphas        self.alphas = np.asarray(alphas)         self.fit_intercept = fit_intercept         self.normalize = normalize         self.scoring = scoring


Question: integers in RidgeCV alpha making one of the alphas a float fixes the problem. This should be handled internally. Python3.6 integers in RidgeCV alpha making one of the alphas a float fixes the problem. This should be handled internally. Python3.6

a one-versus-all approach. Concretely, this is implemented by taking     advantage of the multi-variate response support in Ridge.     """<ins></ins>     def __init__(self, alphas=(0.1, 1.0, 10.0), fit_intercept=True,                  normalize=False, scoring=None, cv=None, class_weight=None):         super(RidgeClassifierCV, self).__init__(


Question: loadsampleimages uses deprecated imread DeprecationWarning: is deprecated! is deprecated in SciPy 1.0.0, and will be removed in 1.2.0.

>>> first_img_data.dtype               #doctest: +SKIP     dtype('uint8')     """    # Try to import imread from scipy. We do this lazily here to prevent    # this module from depending on PIL.    try:        try:            from scipy.misc import imread        except ImportError:            from scipy.misc.pilutil import imread    except ImportError:        raise ImportError("The Python Imaging Library (PIL) "                          "is required to load data from jpeg files")    # import PIL only when needed    from ..externals._pilutil import imread     module_path = join(dirname(__file__), "images")     with open(join(module_path, 'README.txt')) as f:         descr = f.read()diff --git a/sklearn/datasets/lfw.py b/sklearn/datasets/lfw.py-- a/sklearn/datasets/lfw.py++ b/sklearn/datasets/lfw.py


Question: loadsampleimages uses deprecated imread DeprecationWarning: is deprecated! is deprecated in SciPy 1.0.0, and will be removed in 1.2.0.

from .base import get_data_home, _fetch_remote, RemoteFileMetadata from ..utils import Bunch from ..externals.joblib import Memory<del></del> from ..externals.six import b  logger = logging.getLogger(__name__)


Question: loadsampleimages uses deprecated imread DeprecationWarning: is deprecated! is deprecated in SciPy 1.0.0, and will be removed in 1.2.0.

def _load_imgs(file_paths, slice_, color, resize):     """Internally used to load images"""    # Try to import imread and imresize from PIL. We do this here to prevent    # the whole sklearn.datasets module from depending on PIL.    try:        try:            from scipy.misc import imread        except ImportError:            from scipy.misc.pilutil import imread        from scipy.misc import imresize    except ImportError:        raise ImportError("The Python Imaging Library (PIL)"                          " is required to load data from jpeg files")    # import PIL only when needed    from ..externals._pilutil import imread, imresize      # compute the portion of the images to load to respect the slice_ parameter     # given by the callerdiff --git a/sklearn/externals/_pilutil.py b/sklearn/externals/_pilutil.pynew file mode 100644-- /dev/null++ b/sklearn/externals/_pilutil.py


Question: loadsampleimages uses deprecated imread DeprecationWarning: is deprecated! is deprecated in SciPy 1.0.0, and will be removed in 1.2.0.

<ins>"""A collection of image utilities using the Python Imaging Library (PIL).This is a local version of utility functions from scipy that are wrapping PILfunctionality. These functions are deprecated in scipy 1.0.0 and will beremoved in scipy 1.2.0. Therefore, the functionality used in sklearn is copiedhere. This file is taken from scipy/misc/pilutil.py in scipy1.0.0. Modifications include: making this module importable if pillow is notinstalled, removal of DeprecationWarning, removal of functions scikit-learndoes not need.Copyright (c) 2001, 2002 Enthought, Inc.All rights reserved.Copyright (c) 2003-2017 SciPy Developers.All rights reserved.Redistribution and use in source and binary forms, with or withoutmodification, are permitted provided that the following conditions are met:  a. Redistributions of source code must retain the above copyright notice,     this list of conditions and the following disclaimer.  b. Redistributions in binary form must reproduce the above copyright     notice, this list of conditions and the following disclaimer in the     documentation and/or other materials provided with the distribution.  c. Neither the name of Enthought nor the names of the SciPy Developers     may be used to endorse or promote products derived from this software     without specific prior written permission.THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THEIMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSEARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORSBE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OFSUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESSINTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER INCONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OFTHE POSSIBILITY OF SUCH DAMAGE."""from __future__ import division, print_function, absolute_importimport numpyimport tempfilefrom numpy import (amin, amax, ravel, asarray, arange, ones, newaxis,                   transpose, iscomplexobj, uint8, issubdtype, array)# Modification of original scipy pilutil.py to make this module importable if# pillow is not installed. If pillow is not installed, functions will raise# ImportError when called.try:    try:        from PIL import Image    except ImportError:        import Image    pillow_installed = True    if not hasattr(Image, 'frombytes'):        Image.frombytes = Image.fromstringexcept ImportError:    pillow_installed = False__all__ = ['bytescale', 'imread', 'imsave', 'fromimage', 'toimage', 'imresize']def bytescale(data, cmin=None, cmax=None, high=255, low=0):    """    Byte scales an array (image).    Byte scaling means converting the input image to uint8 dtype and scaling    the range to ``(low, high)`` (default 0-255).    If the input image already has dtype uint8, no scaling is done.    This function is only available if Python Imaging Library (PIL) is installed.    Parameters    ----------    data : ndarray        PIL image data array.    cmin : scalar, optional        Bias scaling of small values. Default is ``data.min()``.    cmax : scalar, optional        Bias scaling of large values. Default is ``data.max()``.    high : scalar, optional        Scale max value to `high`.  Default is 255.    low : scalar, optional        Scale min value to `low`.  Default is 0.    Returns    -------    img_array : uint8 ndarray        The byte-scaled array.    Examples    --------    >>> from scipy.misc import bytescale    >>> img = np.array([[ 91.06794177,   3.39058326,  84.4221549 ],    ...                 [ 73.88003259,  80.91433048,   4.88878881],    ...                 [ 51.53875334,  34.45808177,  27.5873488 ]])    >>> bytescale(img)    array([[255,   0, 236],           [205, 225,   4],           [140,  90,  70]], dtype=uint8)    >>> bytescale(img, high=200, low=100)    array([[200, 100, 192],           [180, 188, 102],           [155, 135, 128]], dtype=uint8)    >>> bytescale(img, cmin=0, cmax=255)    array([[91,  3, 84],           [74, 81,  5],           [52, 34, 28]], dtype=uint8)    """    if data.dtype == uint8:        return data    if high > 255:        raise ValueError("`high` should be less than or equal to 255.")    if low < 0:        raise ValueError("`low` should be greater than or equal to 0.")    if high < low:        raise ValueError("`high` should be greater than or equal to `low`.")    if cmin is None:        cmin = data.min()    if cmax is None:        cmax = data.max()    cscale = cmax - cmin    if cscale < 0:        raise ValueError("`cmax` should be larger than `cmin`.")    elif cscale == 0:        cscale = 1    scale = float(high - low) / cscale    bytedata = (data - cmin) * scale + low    return (bytedata.clip(low, high) + 0.5).astype(uint8)def imread(name, flatten=False, mode=None):    """    Read an image from a file as an array.    This function is only available if Python Imaging Library (PIL) is installed.    Parameters    ----------    name : str or file object        The file name or file object to be read.    flatten : bool, optional        If True, flattens the color layers into a single gray-scale layer.    mode : str, optional        Mode to convert image to, e.g. ``'RGB'``.  See the Notes for more        details.    Returns    -------    imread : ndarray        The array obtained by reading the image.    Notes    -----    `imread` uses the Python Imaging Library (PIL) to read an image.    The following notes are from the PIL documentation.    `mode` can be one of the following strings:    * 'L' (8-bit pixels, black and white)    * 'P' (8-bit pixels, mapped to any other mode using a color palette)    * 'RGB' (3x8-bit pixels, true color)    * 'RGBA' (4x8-bit pixels, true color with transparency mask)    * 'CMYK' (4x8-bit pixels, color separation)    * 'YCbCr' (3x8-bit pixels, color video format)    * 'I' (32-bit signed integer pixels)    * 'F' (32-bit floating point pixels)    PIL also provides limited support for a few special modes, including    'LA' ('L' with alpha), 'RGBX' (true color with padding) and 'RGBa'    (true color with premultiplied alpha).    When translating a color image to black and white (mode 'L', 'I' or    'F'), the library uses the ITU-R 601-2 luma transform::        L = R * 299/1000 + G * 587/1000 + B * 114/1000    When `flatten` is True, the image is converted using mode 'F'.    When `mode` is not None and `flatten` is True, the image is first    converted according to `mode`, and the result is then flattened using    mode 'F'.    """    if not pillow_installed:        raise ImportError("The Python Imaging Library (PIL) "                          "is required to load data from jpeg files")    im = Image.open(name)    return fromimage(im, flatten=flatten, mode=mode)def imsave(name, arr, format=None):    """    Save an array as an image.    This function is only available if Python Imaging Library (PIL) is installed.    .. warning::        This function uses `bytescale` under the hood to rescale images to use        the full (0, 255) range if ``mode`` is one of ``None, 'L', 'P', 'l'``.        It will also cast data for 2-D images to ``uint32`` for ``mode=None``        (which is the default).    Parameters    ----------    name : str or file object        Output file name or file object.    arr : ndarray, MxN or MxNx3 or MxNx4        Array containing image values.  If the shape is ``MxN``, the array        represents a grey-level image.  Shape ``MxNx3`` stores the red, green        and blue bands along the last dimension.  An alpha layer may be        included, specified as the last colour band of an ``MxNx4`` array.    format : str        Image format. If omitted, the format to use is determined from the        file name extension. If a file object was used instead of a file name,        this parameter should always be used.    Examples    --------    Construct an array of gradient intensity values and save to file:    >>> from scipy.misc import imsave    >>> x = np.zeros((255, 255))    >>> x = np.zeros((255, 255), dtype=np.uint8)    >>> x[:] = np.arange(255)    >>> imsave('gradient.png', x)    Construct an array with three colour bands (R, G, B) and store to file:    >>> rgb = np.zeros((255, 255, 3), dtype=np.uint8)    >>> rgb[..., 0] = np.arange(255)    >>> rgb[..., 1] = 55    >>> rgb[..., 2] = 1 - np.arange(255)    >>> imsave('rgb_gradient.png', rgb)    """    im = toimage(arr, channel_axis=2)    if format is None:        im.save(name)    else:        im.save(name, format)    returndef fromimage(im, flatten=False, mode=None):    """    Return a copy of a PIL image as a numpy array.    This function is only available if Python Imaging Library (PIL) is installed.    Parameters    ----------    im : PIL image        Input image.    flatten : bool        If true, convert the output to grey-scale.    mode : str, optional        Mode to convert image to, e.g. ``'RGB'``.  See the Notes of the        `imread` docstring for more details.    Returns    -------    fromimage : ndarray        The different colour bands/channels are stored in the        third dimension, such that a grey-image is MxN, an        RGB-image MxNx3 and an RGBA-image MxNx4.    """    if not pillow_installed:        raise ImportError("The Python Imaging Library (PIL) "                          "is required to load data from jpeg files")    if not Image.isImageType(im):        raise TypeError("Input is not a PIL image.")    if mode is not None:        if mode != im.mode:            im = im.convert(mode)    elif im.mode == 'P':        # Mode 'P' means there is an indexed "palette".  If we leave the mode        # as 'P', then when we do `a = array(im)` below, `a` will be a 2-D        # containing the indices into the palette, and not a 3-D array        # containing the RGB or RGBA values.        if 'transparency' in im.info:            im = im.convert('RGBA')        else:            im = im.convert('RGB')    if flatten:        im = im.convert('F')    elif im.mode == '1':        # Workaround for crash in PIL. When im is 1-bit, the call array(im)        # can cause a seg. fault, or generate garbage. See        # https://github.com/scipy/scipy/issues/2138 and        # https://github.com/python-pillow/Pillow/issues/350.        #        # This converts im from a 1-bit image to an 8-bit image.        im = im.convert('L')    a = array(im)    return a_errstr = "Mode is unknown or incompatible with input array shape."def toimage(arr, high=255, low=0, cmin=None, cmax=None, pal=None,            mode=None, channel_axis=None):    """Takes a numpy array and returns a PIL image.    This function is only available if Python Imaging Library (PIL) is installed.    The mode of the PIL image depends on the array shape and the `pal` and    `mode` keywords.    For 2-D arrays, if `pal` is a valid (N,3) byte-array giving the RGB values    (from 0 to 255) then ``mode='P'``, otherwise ``mode='L'``, unless mode    is given as 'F' or 'I' in which case a float and/or integer array is made.    .. warning::        This function uses `bytescale` under the hood to rescale images to use        the full (0, 255) range if ``mode`` is one of ``None, 'L', 'P', 'l'``.        It will also cast data for 2-D images to ``uint32`` for ``mode=None``        (which is the default).    Notes    -----    For 3-D arrays, the `channel_axis` argument tells which dimension of the    array holds the channel data.    For 3-D arrays if one of the dimensions is 3, the mode is 'RGB'    by default or 'YCbCr' if selected.    The numpy array must be either 2 dimensional or 3 dimensional.    """    if not pillow_installed:        raise ImportError("The Python Imaging Library (PIL) "                          "is required to load data from jpeg files")    data = asarray(arr)    if iscomplexobj(data):        raise ValueError("Cannot convert a complex-valued array.")    shape = list(data.shape)    valid = len(shape) == 2 or ((len(shape) == 3) and                                ((3 in shape) or (4 in shape)))    if not valid:        raise ValueError("'arr' does not have a suitable array shape for "                         "any mode.")    if len(shape) == 2:        shape = (shape[1], shape[0])  # columns show up first        if mode == 'F':            data32 = data.astype(numpy.float32)            image = Image.frombytes(mode, shape, data32.tostring())            return image        if mode in [None, 'L', 'P']:            bytedata = bytescale(data, high=high, low=low,                                 cmin=cmin, cmax=cmax)            image = Image.frombytes('L', shape, bytedata.tostring())            if pal is not None:                image.putpalette(asarray(pal, dtype=uint8).tostring())                # Becomes a mode='P' automagically.            elif mode == 'P':  # default gray-scale                pal = (arange(0, 256, 1, dtype=uint8)[:, newaxis] *                       ones((3,), dtype=uint8)[newaxis, :])                image.putpalette(asarray(pal, dtype=uint8).tostring())            return image        if mode == '1':  # high input gives threshold for 1            bytedata = (data > high)            image = Image.frombytes('1', shape, bytedata.tostring())            return image        if cmin is None:            cmin = amin(ravel(data))        if cmax is None:            cmax = amax(ravel(data))        data = (data*1.0 - cmin)*(high - low)/(cmax - cmin) + low        if mode == 'I':            data32 = data.astype(numpy.uint32)            image = Image.frombytes(mode, shape, data32.tostring())        else:            raise ValueError(_errstr)        return image    # if here then 3-d array with a 3 or a 4 in the shape length.    # Check for 3 in datacube shape --- 'RGB' or 'YCbCr'    if channel_axis is None:        if (3 in shape):            ca = numpy.flatnonzero(asarray(shape) == 3)[0]        else:            ca = numpy.flatnonzero(asarray(shape) == 4)            if len(ca):                ca = ca[0]            else:                raise ValueError("Could not find channel dimension.")    else:        ca = channel_axis    numch = shape[ca]    if numch not in [3, 4]:        raise ValueError("Channel axis dimension is not valid.")    bytedata = bytescale(data, high=high, low=low, cmin=cmin, cmax=cmax)    if ca == 2:        strdata = bytedata.tostring()        shape = (shape[1], shape[0])    elif ca == 1:        strdata = transpose(bytedata, (0, 2, 1)).tostring()        shape = (shape[2], shape[0])    elif ca == 0:        strdata = transpose(bytedata, (1, 2, 0)).tostring()        shape = (shape[2], shape[1])    if mode is None:        if numch == 3:            mode = 'RGB'        else:            mode = 'RGBA'    if mode not in ['RGB', 'RGBA', 'YCbCr', 'CMYK']:        raise ValueError(_errstr)    if mode in ['RGB', 'YCbCr']:        if numch != 3:            raise ValueError("Invalid array shape for mode.")    if mode in ['RGBA', 'CMYK']:        if numch != 4:            raise ValueError("Invalid array shape for mode.")    # Here we know data and mode is correct    image = Image.frombytes(mode, shape, strdata)    return imagedef imresize(arr, size, interp='bilinear', mode=None):    """    Resize an image.    This function is only available if Python Imaging Library (PIL) is installed.    .. warning::        This function uses `bytescale` under the hood to rescale images to use        the full (0, 255) range if ``mode`` is one of ``None, 'L', 'P', 'l'``.        It will also cast data for 2-D images to ``uint32`` for ``mode=None``        (which is the default).    Parameters    ----------    arr : ndarray        The array of image to be resized.    size : int, float or tuple        * int   - Percentage of current size.        * float - Fraction of current size.        * tuple - Size of the output image (height, width).    interp : str, optional        Interpolation to use for re-sizing ('nearest', 'lanczos', 'bilinear',        'bicubic' or 'cubic').    mode : str, optional        The PIL image mode ('P', 'L', etc.) to convert `arr` before resizing.        If ``mode=None`` (the default), 2-D images will be treated like        ``mode='L'``, i.e. casting to long integer.  For 3-D and 4-D arrays,        `mode` will be set to ``'RGB'`` and ``'RGBA'`` respectively.    Returns    -------    imresize : ndarray        The resized array of image.    See Also    --------    toimage : Implicitly used to convert `arr` according to `mode`.    scipy.ndimage.zoom : More generic implementation that does not use PIL.    """    im = toimage(arr, mode=mode)    ts = type(size)    if issubdtype(ts, numpy.signedinteger):        percent = size / 100.0        size = tuple((array(im.size)*percent).astype(int))    elif issubdtype(type(size), numpy.floating):        size = tuple((array(im.size)*size).astype(int))    else:        size = (size[1], size[0])    func = {'nearest': 0, 'lanczos': 1, 'bilinear': 2, 'bicubic': 3, 'cubic': 3}    imnew = im.resize(size, resample=func[interp])    return fromimage(imnew)</ins>


Question: Add common test to ensure all(predict(X[mask]) == predict(X)[mask]) I don't think we currently test that estimator predictions/transformations are invariant whether performed in batch or on subsets of a dataset. For some fitted estimator , data and any boolean mask of length , we need: where is any of {, , , , }. Testing that predictions for individual samples match the predictions across the dataset might be sufficient. This should be to common tests at Indeed, reports that this is broken for one-vs-one classification. :'(

for check in _yield_clustering_checks(name, estimator):             yield check     yield check_fit2d_predict1d<ins>    yield check_methods_subset_invariance</ins>     if name != 'GaussianProcess':  # FIXME         # XXX GaussianProcess deprecated in 0.20         yield check_fit2d_1sample


Question: Add common test to ensure all(predict(X[mask]) == predict(X)[mask]) I don't think we currently test that estimator predictions/transformations are invariant whether performed in batch or on subsets of a dataset. For some fitted estimator , data and any boolean mask of length , we need: where is any of {, , , , }. Testing that predictions for individual samples match the predictions across the dataset might be sufficient. This should be to common tests at Indeed, reports that this is broken for one-vs-one classification. :'(

getattr(estimator, method), X[0])  <ins>def _apply_func(func, X):    # apply function on the whole set and on mini batches    result_full = func(X)    n_features = X.shape[1]    result_by_batch = [func(batch.reshape(1, n_features))                       for batch in X]    # func can output tuple (e.g. score_samples)    if type(result_full) == tuple:        result_full = result_full[0]        result_by_batch = list(map(lambda x: x[0], result_by_batch))    return np.ravel(result_full), np.ravel(result_by_batch)@ignore_warnings(category=(DeprecationWarning, FutureWarning))def check_methods_subset_invariance(name, estimator_orig):    # check that method gives invariant results if applied    # on mini bathes or the whole set    rnd = np.random.RandomState(0)    X = 3 * rnd.uniform(size=(20, 3))    X = pairwise_estimator_convert_X(X, estimator_orig)    y = X[:, 0].astype(np.int)    estimator = clone(estimator_orig)    y = multioutput_estimator_convert_y_2d(estimator, y)    if hasattr(estimator, "n_components"):        estimator.n_components = 1    if hasattr(estimator, "n_clusters"):        estimator.n_clusters = 1    set_random_state(estimator, 1)    estimator.fit(X, y)    for method in ["predict", "transform", "decision_function",                   "score_samples", "predict_proba"]:        msg = ("{method} of {name} is not invariant when applied "               "to a subset.").format(method=method, name=name)        # TODO remove cases when corrected        if (name, method) in [('SVC', 'decision_function'),                              ('SparsePCA', 'transform'),                              ('MiniBatchSparsePCA', 'transform'),                              ('BernoulliRBM', 'score_samples')]:            raise SkipTest(msg)        if hasattr(estimator, method):            result_full, result_by_batch = _apply_func(                getattr(estimator, method), X)            assert_allclose(result_full, result_by_batch,                            atol=1e-7, err_msg=msg)</ins> @ignore_warnings def check_fit2d_1sample(name, estimator_orig):     # Check that fitting a 2d array with only one sample either works or


Question: Polynomial Features for sparse data I'm not sure if that came up before but PolynomialFeatures doesn't support sparse data, which is not great. Should be easy but I haven't checked ;)

-------         self : instance         """        n_samples, n_features = check_array(X).shape        n_samples, n_features = check_array(X, accept_sparse=True).shape         combinations = self._combinations(n_features, self.degree,                                           self.interaction_only,                                           self.include_bias)


Question: Polynomial Features for sparse data I'm not sure if that came up before but PolynomialFeatures doesn't support sparse data, which is not great. Should be easy but I haven't checked ;)

Parameters         ----------        X : array-like, shape [n_samples, n_features]        X : array-like or sparse matrix, shape [n_samples, n_features]             The data to transform, row by row.            Sparse input should preferably be in CSC format.          Returns         -------        XP : np.ndarray shape [n_samples, NP]        XP : np.ndarray or CSC sparse matrix, shape [n_samples, NP]             The matrix of features, where NP is the number of polynomial             features generated from the combination of inputs.         """         check_is_fitted(self, ['n_input_features_', 'n_output_features_'])         X = check_array(X, dtype=FLOAT_DTYPES)        X = check_array(X, dtype=FLOAT_DTYPES, accept_sparse='csc')         n_samples, n_features = X.shape          if n_features != self.n_input_features_:             raise ValueError("X shape does not match training shape")         # allocate output data        XP = np.empty((n_samples, self.n_output_features_), dtype=X.dtype)         combinations = self._combinations(n_features, self.degree,                                           self.interaction_only,                                           self.include_bias)        for i, c in enumerate(combinations):            XP[:, i] = X[:, c].prod(1)        if sparse.isspmatrix(X):            columns = []            for comb in combinations:                if comb:                    out_col = 1                    for col_idx in comb:                        out_col = X[:, col_idx].multiply(out_col)                    columns.append(out_col)                else:                    columns.append(sparse.csc_matrix(np.ones((X.shape[0], 1))))            XP = sparse.hstack(columns, dtype=X.dtype).tocsc()        else:            XP = np.empty((n_samples, self.n_output_features_), dtype=X.dtype)            for i, comb in enumerate(combinations):                XP[:, i] = X[:, comb].prod(1)          return XP


Question: [RFC] Dissociate NaN and Inf when considering forceallfinite in checkarray Due to changes proposed in , it seems that as currently a main limitation. will force both and to be rejected. If preprocessing methods (whenever this is possible) should let pass , this argument is not enough permissive. Before to implement anything, I think it could be good to have some feedback on the way to go. I see the following solutions: could still accept a bool to preserve the behaviour. Additionally, it could accept an to filter only . proposes to have an additional argument . was worried that it makes to complex. a private function (similarly to removing the numpy version checking) in the which can be shared between the preprocessing methods. They are the solutions that I have in mind for the moment but anything else is welcomed. I would be grateful for any insight.

warnings.simplefilter('ignore', NonBLASDotWarning)  def _assert_all_finite(X):def _assert_all_finite(X, allow_nan=False):     """Like assert_all_finite, but only for ndarray."""     if _get_config()['assume_finite']:         return


Question: [RFC] Dissociate NaN and Inf when considering forceallfinite in checkarray Due to changes proposed in , it seems that as currently a main limitation. will force both and to be rejected. If preprocessing methods (whenever this is possible) should let pass , this argument is not enough permissive. Before to implement anything, I think it could be good to have some feedback on the way to go. I see the following solutions: could still accept a bool to preserve the behaviour. Additionally, it could accept an to filter only . proposes to have an additional argument . was worried that it makes to complex. a private function (similarly to removing the numpy version checking) in the which can be shared between the preprocessing methods. They are the solutions that I have in mind for the moment but anything else is welcomed. I would be grateful for any insight.

# First try an O(n) time, O(1) space solution for the common case that     # everything is finite; fall back to O(n) space np.isfinite to prevent     # false positives from overflow in sum method.    if (X.dtype.char in np.typecodes['AllFloat'] and not np.isfinite(X.sum())            and not np.isfinite(X).all()):        raise ValueError("Input contains NaN, infinity"                         " or a value too large for %r." % X.dtype)def assert_all_finite(X):    is_float = X.dtype.kind in 'fc'    if is_float and np.isfinite(X.sum()):        pass    elif is_float:        msg_err = "Input contains {} or a value too large for {!r}."        if (allow_nan and np.isinf(X).any() or                not allow_nan and not np.isfinite(X).all()):            type_err = 'infinity' if allow_nan else 'NaN, infinity'            raise ValueError(msg_err.format(type_err, X.dtype))def assert_all_finite(X, allow_nan=False):     """Throw a ValueError if X contains NaN or infinity.      Parameters     ----------     X : array or sparse matrix    allow_nan : bool     """    _assert_all_finite(X.data if sp.issparse(X) else X)    _assert_all_finite(X.data if sp.issparse(X) else X, allow_nan)   def as_float_array(X, copy=True, force_all_finite=True):


Question: [RFC] Dissociate NaN and Inf when considering forceallfinite in checkarray Due to changes proposed in , it seems that as currently a main limitation. will force both and to be rejected. If preprocessing methods (whenever this is possible) should let pass , this argument is not enough permissive. Before to implement anything, I think it could be good to have some feedback on the way to go. I see the following solutions: could still accept a bool to preserve the behaviour. Additionally, it could accept an to filter only . proposes to have an additional argument . was worried that it makes to complex. a private function (similarly to removing the numpy version checking) in the which can be shared between the preprocessing methods. They are the solutions that I have in mind for the moment but anything else is welcomed. I would be grateful for any insight.

If True, a copy of X will be created. If False, a copy may still be         returned if X's dtype is not a floating point type.     force_all_finite : boolean (default=True)        Whether to raise an error on np.inf and np.nan in X.    force_all_finite : boolean or 'allow-nan', (default=True)        Whether to raise an error on np.inf and np.nan in X. The possibilities        are:        - True: Force all values of X to be finite.        - False: accept both np.inf and np.nan in X.        - 'allow-nan':  accept  only  np.nan  values in  X.  Values  cannot  be          infinite.        .. versionadded:: 0.20           ``force_all_finite`` accepts the string ``'allow-nan'``.      Returns     -------


Question: [RFC] Dissociate NaN and Inf when considering forceallfinite in checkarray Due to changes proposed in , it seems that as currently a main limitation. will force both and to be rejected. If preprocessing methods (whenever this is possible) should let pass , this argument is not enough permissive. Before to implement anything, I think it could be good to have some feedback on the way to go. I see the following solutions: could still accept a bool to preserve the behaviour. Additionally, it could accept an to filter only . proposes to have an additional argument . was worried that it makes to complex. a private function (similarly to removing the numpy version checking) in the which can be shared between the preprocessing methods. They are the solutions that I have in mind for the moment but anything else is welcomed. I would be grateful for any insight.

Whether a forced copy will be triggered. If copy=False, a copy might         be triggered by a conversion.     force_all_finite : boolean        Whether to raise an error on np.inf and np.nan in X.    force_all_finite : boolean or 'allow-nan', (default=True)        Whether to raise an error on np.inf and np.nan in X. The possibilities        are:        - True: Force all values of X to be finite.        - False: accept both np.inf and np.nan in X.        - 'allow-nan':  accept  only  np.nan  values in  X.  Values  cannot  be          infinite.        .. versionadded:: 0.20           ``force_all_finite`` accepts the string ``'allow-nan'``.      Returns     -------


Question: [RFC] Dissociate NaN and Inf when considering forceallfinite in checkarray Due to changes proposed in , it seems that as currently a main limitation. will force both and to be rejected. If preprocessing methods (whenever this is possible) should let pass , this argument is not enough permissive. Before to implement anything, I think it could be good to have some feedback on the way to go. I see the following solutions: could still accept a bool to preserve the behaviour. Additionally, it could accept an to filter only . proposes to have an additional argument . was worried that it makes to complex. a private function (similarly to removing the numpy version checking) in the which can be shared between the preprocessing methods. They are the solutions that I have in mind for the moment but anything else is welcomed. I would be grateful for any insight.

warnings.warn("Can't check %s sparse matrix for nan or inf."                           % spmatrix.format)         else:            _assert_all_finite(spmatrix.data)            _assert_all_finite(spmatrix.data,                               allow_nan=force_all_finite == 'allow-nan')     return spmatrix


Question: [RFC] Dissociate NaN and Inf when considering forceallfinite in checkarray Due to changes proposed in , it seems that as currently a main limitation. will force both and to be rejected. If preprocessing methods (whenever this is possible) should let pass , this argument is not enough permissive. Before to implement anything, I think it could be good to have some feedback on the way to go. I see the following solutions: could still accept a bool to preserve the behaviour. Additionally, it could accept an to filter only . proposes to have an additional argument . was worried that it makes to complex. a private function (similarly to removing the numpy version checking) in the which can be shared between the preprocessing methods. They are the solutions that I have in mind for the moment but anything else is welcomed. I would be grateful for any insight.

Whether a forced copy will be triggered. If copy=False, a copy might         be triggered by a conversion.     force_all_finite : boolean (default=True)        Whether to raise an error on np.inf and np.nan in X.    force_all_finite : boolean or 'allow-nan', (default=True)        Whether to raise an error on np.inf and np.nan in X. The possibilities        are:        - True: Force all values of X to be finite.        - False: accept both np.inf and np.nan in X.        - 'allow-nan':  accept  only  np.nan  values in  X.  Values  cannot  be          infinite.        .. versionadded:: 0.20           ``force_all_finite`` accepts the string ``'allow-nan'``.      ensure_2d : boolean (default=True)         Whether to raise a value error if X is not 2d.


Question: [RFC] Dissociate NaN and Inf when considering forceallfinite in checkarray Due to changes proposed in , it seems that as currently a main limitation. will force both and to be rejected. If preprocessing methods (whenever this is possible) should let pass , this argument is not enough permissive. Before to implement anything, I think it could be good to have some feedback on the way to go. I see the following solutions: could still accept a bool to preserve the behaviour. Additionally, it could accept an to filter only . proposes to have an additional argument . was worried that it makes to complex. a private function (similarly to removing the numpy version checking) in the which can be shared between the preprocessing methods. They are the solutions that I have in mind for the moment but anything else is welcomed. I would be grateful for any insight.

# list of accepted types.             dtype = dtype[0] <ins>    if force_all_finite not in (True, False, 'allow-nan'):        raise ValueError('force_all_finite should be a bool or "allow-nan"'                         '. Got {!r} instead'.format(force_all_finite))</ins>     if estimator is not None:         if isinstance(estimator, six.string_types):             estimator_name = estimator


Question: [RFC] Dissociate NaN and Inf when considering forceallfinite in checkarray Due to changes proposed in , it seems that as currently a main limitation. will force both and to be rejected. If preprocessing methods (whenever this is possible) should let pass , this argument is not enough permissive. Before to implement anything, I think it could be good to have some feedback on the way to go. I see the following solutions: could still accept a bool to preserve the behaviour. Additionally, it could accept an to filter only . proposes to have an additional argument . was worried that it makes to complex. a private function (similarly to removing the numpy version checking) in the which can be shared between the preprocessing methods. They are the solutions that I have in mind for the moment but anything else is welcomed. I would be grateful for any insight.

raise ValueError("Found array with dim %d. %s expected <= 2."                              % (array.ndim, estimator_name))         if force_all_finite:            _assert_all_finite(array)            _assert_all_finite(array,                               allow_nan=force_all_finite == 'allow-nan')      shape_repr = _shape_repr(array.shape)     if ensure_min_samples > 0:


Question: [RFC] Dissociate NaN and Inf when considering forceallfinite in checkarray Due to changes proposed in , it seems that as currently a main limitation. will force both and to be rejected. If preprocessing methods (whenever this is possible) should let pass , this argument is not enough permissive. Before to implement anything, I think it could be good to have some feedback on the way to go. I see the following solutions: could still accept a bool to preserve the behaviour. Additionally, it could accept an to filter only . proposes to have an additional argument . was worried that it makes to complex. a private function (similarly to removing the numpy version checking) in the which can be shared between the preprocessing methods. They are the solutions that I have in mind for the moment but anything else is welcomed. I would be grateful for any insight.

Whether a forced copy will be triggered. If copy=False, a copy might         be triggered by a conversion.     force_all_finite : boolean (default=True)    force_all_finite : boolean or 'allow-nan', (default=True)         Whether to raise an error on np.inf and np.nan in X. This parameter         does not influence whether y can have np.inf or np.nan values.        The possibilities are:        - True: Force all values of X to be finite.        - False: accept both np.inf and np.nan in X.        - 'allow-nan':  accept  only  np.nan  values in  X.  Values  cannot  be          infinite.        .. versionadded:: 0.20           ``force_all_finite`` accepts the string ``'allow-nan'``.      ensure_2d : boolean (default=True)         Whether to make X at least 2d.


Question: Move imputation out of preprocessing While we're considering additional imputers, I've wondered whether preprocessing is the right place for it. Yes, it is a preprocessing step before other learning, but it often makes use of other supervised and unsupervised learners and hence is a learning task of its own. And preprocessing is getting a bit cramped. We could also do as with other models and have imputers appear in modules on the basis of how they work rather than function: could appear in neighbors for instance. could appear where..? And the basic in dummy? probably not. In practice I think it is more useful for users to , akin to our clusterers and decomposition, and unlike our predictors and outlier detectors that are grouped by algorithm.

from sklearn.datasets import load_boston from sklearn.ensemble import RandomForestRegressor from sklearn.pipeline import Pipelinefrom sklearn.preprocessing import Imputerfrom sklearn.impute import SimpleImputer from sklearn.model_selection import cross_val_score  rng = np.random.RandomState(0)


Question: Move imputation out of preprocessing While we're considering additional imputers, I've wondered whether preprocessing is the right place for it. Yes, it is a preprocessing step before other learning, but it often makes use of other supervised and unsupervised learners and hence is a learning task of its own. And preprocessing is getting a bit cramped. We could also do as with other models and have imputers appear in modules on the basis of how they work rather than function: could appear in neighbors for instance. could appear where..? And the basic in dummy? probably not. In practice I think it is more useful for users to , akin to our clusterers and decomposition, and unlike our predictors and outlier detectors that are grouped by algorithm.

X_missing = X_full.copy() X_missing[np.where(missing_samples)[0], missing_features] = 0 y_missing = y_full.copy()estimator = Pipeline([("imputer", Imputer(missing_values=0,                                          strategy="mean",                                          axis=0)),estimator = Pipeline([("imputer", SimpleImputer(missing_values=0,                                                strategy="mean",                                                axis=0)),                       ("forest", RandomForestRegressor(random_state=0,                                                        n_estimators=100))]) score = cross_val_score(estimator, X_missing, y_missing).mean()diff --git a/sklearn/__init__.py b/sklearn/__init__.py-- a/sklearn/__init__.py++ b/sklearn/__init__.py


Question: Move imputation out of preprocessing While we're considering additional imputers, I've wondered whether preprocessing is the right place for it. Yes, it is a preprocessing step before other learning, but it often makes use of other supervised and unsupervised learners and hence is a learning task of its own. And preprocessing is getting a bit cramped. We could also do as with other models and have imputers appear in modules on the basis of how they work rather than function: could appear in neighbors for instance. could appear where..? And the basic in dummy? probably not. In practice I think it is more useful for users to , akin to our clusterers and decomposition, and unlike our predictors and outlier detectors that are grouped by algorithm.

'mixture', 'model_selection', 'multiclass', 'multioutput',                'naive_bayes', 'neighbors', 'neural_network', 'pipeline',                'preprocessing', 'random_projection', 'semi_supervised',               'svm', 'tree', 'discriminant_analysis',               'svm', 'tree', 'discriminant_analysis', 'impute',                # Non-modules:                'clone', 'get_config', 'set_config', 'config_context'] diff --git a/sklearn/impute.py b/sklearn/impute.pynew file mode 100644-- /dev/null++ b/sklearn/impute.py


Question: Move imputation out of preprocessing While we're considering additional imputers, I've wondered whether preprocessing is the right place for it. Yes, it is a preprocessing step before other learning, but it often makes use of other supervised and unsupervised learners and hence is a learning task of its own. And preprocessing is getting a bit cramped. We could also do as with other models and have imputers appear in modules on the basis of how they work rather than function: could appear in neighbors for instance. could appear where..? And the basic in dummy? probably not. In practice I think it is more useful for users to , akin to our clusterers and decomposition, and unlike our predictors and outlier detectors that are grouped by algorithm.

"""Transformers for missing value imputation"""# Authors: Nicolas Tresegnie <nicolas.tresegnie@gmail.com># License: BSD 3 clauseimport warningsimport numpy as npimport numpy.ma as mafrom scipy import sparsefrom scipy import statsfrom .base import BaseEstimator, TransformerMixinfrom .utils import check_arrayfrom .utils.sparsefuncs import _get_medianfrom .utils.validation import check_is_fittedfrom .utils.validation import FLOAT_DTYPESfrom .externals import sixzip = six.moves.zipmap = six.moves.map__all__ = [    'SimpleImputer',]def _get_mask(X, value_to_mask):    """Compute the boolean mask X == missing_values."""    if value_to_mask == "NaN" or np.isnan(value_to_mask):        return np.isnan(X)    else:        return X == value_to_maskdef _most_frequent(array, extra_value, n_repeat):    """Compute the most frequent value in a 1d array extended with       [extra_value] * n_repeat, where extra_value is assumed to be not part       of the array."""    # Compute the most frequent value in array only    if array.size > 0:        mode = stats.mode(array)        most_frequent_value = mode[0][0]        most_frequent_count = mode[1][0]    else:        most_frequent_value = 0        most_frequent_count = 0    # Compare to array + [extra_value] * n_repeat    if most_frequent_count == 0 and n_repeat == 0:        return np.nan    elif most_frequent_count < n_repeat:        return extra_value    elif most_frequent_count > n_repeat:        return most_frequent_value    elif most_frequent_count == n_repeat:        # Ties the breaks. Copy the behaviour of scipy.stats.mode        if most_frequent_value < extra_value:            return most_frequent_value        else:            return extra_valueclass SimpleImputer(BaseEstimator, TransformerMixin):    """Imputation transformer for completing missing values.    Read more in the :ref:`User Guide <impute>`.    Parameters    ----------    missing_values : integer or "NaN", optional (default="NaN")        The placeholder for the missing values. All occurrences of        `missing_values` will be imputed. For missing values encoded as np.nan,        use the string value "NaN".    strategy : string, optional (default="mean")        The imputation strategy.        - If "mean", then replace missing values using the mean along          the axis.        - If "median", then replace missing values using the median along          the axis.        - If "most_frequent", then replace missing using the most frequent          value along the axis.    axis : integer, optional (default=0)        The axis along which to impute.        - If `axis=0`, then impute along columns.        - If `axis=1`, then impute along rows.    verbose : integer, optional (default=0)        Controls the verbosity of the imputer.    copy : boolean, optional (default=True)        If True, a copy of X will be created. If False, imputation will        be done in-place whenever possible. Note that, in the following cases,        a new copy will always be made, even if `copy=False`:        - If X is not an array of floating values;        - If X is sparse and `missing_values=0`;        - If `axis=0` and X is encoded as a CSR matrix;        - If `axis=1` and X is encoded as a CSC matrix.    Attributes    ----------    statistics_ : array of shape (n_features,)        The imputation fill value for each feature if axis == 0.    Notes    -----    - When ``axis=0``, columns which only contained missing values at `fit`      are discarded upon `transform`.    - When ``axis=1``, an exception is raised if there are rows for which it is      not possible to fill in the missing values (e.g., because they only      contain missing values).    """    def __init__(self, missing_values="NaN", strategy="mean",                 axis=0, verbose=0, copy=True):        self.missing_values = missing_values        self.strategy = strategy        self.axis = axis        self.verbose = verbose        self.copy = copy    def fit(self, X, y=None):        """Fit the imputer on X.        Parameters        ----------        X : {array-like, sparse matrix}, shape (n_samples, n_features)            Input data, where ``n_samples`` is the number of samples and            ``n_features`` is the number of features.        Returns        -------        self : SimpleImputer        """        # Check parameters        allowed_strategies = ["mean", "median", "most_frequent"]        if self.strategy not in allowed_strategies:            raise ValueError("Can only use these strategies: {0} "                             " got strategy={1}".format(allowed_strategies,                                                        self.strategy))        if self.axis not in [0, 1]:            raise ValueError("Can only impute missing values on axis 0 and 1, "                             " got axis={0}".format(self.axis))        # Since two different arrays can be provided in fit(X) and        # transform(X), the imputation data will be computed in transform()        # when the imputation is done per sample (i.e., when axis=1).        if self.axis == 0:            X = check_array(X, accept_sparse='csc', dtype=np.float64,                            force_all_finite=False)            if sparse.issparse(X):                self.statistics_ = self._sparse_fit(X,                                                    self.strategy,                                                    self.missing_values,                                                    self.axis)            else:                self.statistics_ = self._dense_fit(X,                                                   self.strategy,                                                   self.missing_values,                                                   self.axis)        return self    def _sparse_fit(self, X, strategy, missing_values, axis):        """Fit the transformer on sparse data."""        # Imputation is done "by column", so if we want to do it        # by row we only need to convert the matrix to csr format.        if axis == 1:            X = X.tocsr()        else:            X = X.tocsc()        # Count the zeros        if missing_values == 0:            n_zeros_axis = np.zeros(X.shape[not axis], dtype=int)        else:            n_zeros_axis = X.shape[axis] - np.diff(X.indptr)        # Mean        if strategy == "mean":            if missing_values != 0:                n_non_missing = n_zeros_axis                # Mask the missing elements                mask_missing_values = _get_mask(X.data, missing_values)                mask_valids = np.logical_not(mask_missing_values)                # Sum only the valid elements                new_data = X.data.copy()                new_data[mask_missing_values] = 0                X = sparse.csc_matrix((new_data, X.indices, X.indptr),                                      copy=False)                sums = X.sum(axis=0)                # Count the elements != 0                mask_non_zeros = sparse.csc_matrix(                    (mask_valids.astype(np.float64),                     X.indices,                     X.indptr), copy=False)                s = mask_non_zeros.sum(axis=0)                n_non_missing = np.add(n_non_missing, s)            else:                sums = X.sum(axis=axis)                n_non_missing = np.diff(X.indptr)            # Ignore the error, columns with a np.nan statistics_            # are not an error at this point. These columns will            # be removed in transform            with np.errstate(all="ignore"):                return np.ravel(sums) / np.ravel(n_non_missing)        # Median + Most frequent        else:            # Remove the missing values, for each column            columns_all = np.hsplit(X.data, X.indptr[1:-1])            mask_missing_values = _get_mask(X.data, missing_values)            mask_valids = np.hsplit(np.logical_not(mask_missing_values),                                    X.indptr[1:-1])            # astype necessary for bug in numpy.hsplit before v1.9            columns = [col[mask.astype(bool, copy=False)]                       for col, mask in zip(columns_all, mask_valids)]            # Median            if strategy == "median":                median = np.empty(len(columns))                for i, column in enumerate(columns):                    median[i] = _get_median(column, n_zeros_axis[i])                return median            # Most frequent            elif strategy == "most_frequent":                most_frequent = np.empty(len(columns))                for i, column in enumerate(columns):                    most_frequent[i] = _most_frequent(column,                                                      0,                                                      n_zeros_axis[i])                return most_frequent    def _dense_fit(self, X, strategy, missing_values, axis):        """Fit the transformer on dense data."""        X = check_array(X, force_all_finite=False)        mask = _get_mask(X, missing_values)        masked_X = ma.masked_array(X, mask=mask)        # Mean        if strategy == "mean":            mean_masked = np.ma.mean(masked_X, axis=axis)            # Avoid the warning "Warning: converting a masked element to nan."            mean = np.ma.getdata(mean_masked)            mean[np.ma.getmask(mean_masked)] = np.nan            return mean        # Median        elif strategy == "median":            if tuple(int(v) for v in np.__version__.split('.')[:2]) < (1, 5):                # In old versions of numpy, calling a median on an array                # containing nans returns nan. This is different is                # recent versions of numpy, which we want to mimic                masked_X.mask = np.logical_or(masked_X.mask,                                              np.isnan(X))            median_masked = np.ma.median(masked_X, axis=axis)            # Avoid the warning "Warning: converting a masked element to nan."            median = np.ma.getdata(median_masked)            median[np.ma.getmaskarray(median_masked)] = np.nan            return median        # Most frequent        elif strategy == "most_frequent":            # scipy.stats.mstats.mode cannot be used because it will no work            # properly if the first element is masked and if its frequency            # is equal to the frequency of the most frequent valid element            # See https://github.com/scipy/scipy/issues/2636            # To be able access the elements by columns            if axis == 0:                X = X.transpose()                mask = mask.transpose()            most_frequent = np.empty(X.shape[0])            for i, (row, row_mask) in enumerate(zip(X[:], mask[:])):                row_mask = np.logical_not(row_mask).astype(np.bool)                row = row[row_mask]                most_frequent[i] = _most_frequent(row, np.nan, 0)            return most_frequent    def transform(self, X):        """Impute all missing values in X.        Parameters        ----------        X : {array-like, sparse matrix}, shape = [n_samples, n_features]            The input data to complete.        """        if self.axis == 0:            check_is_fitted(self, 'statistics_')            X = check_array(X, accept_sparse='csc', dtype=FLOAT_DTYPES,                            force_all_finite=False, copy=self.copy)            statistics = self.statistics_            if X.shape[1] != statistics.shape[0]:                raise ValueError("X has %d features per sample, expected %d"                                 % (X.shape[1], self.statistics_.shape[0]))        # Since two different arrays can be provided in fit(X) and        # transform(X), the imputation data need to be recomputed        # when the imputation is done per sample        else:            X = check_array(X, accept_sparse='csr', dtype=FLOAT_DTYPES,                            force_all_finite=False, copy=self.copy)            if sparse.issparse(X):                statistics = self._sparse_fit(X,                                              self.strategy,                                              self.missing_values,                                              self.axis)            else:                statistics = self._dense_fit(X,                                             self.strategy,                                             self.missing_values,                                             self.axis)        # Delete the invalid rows/columns        invalid_mask = np.isnan(statistics)        valid_mask = np.logical_not(invalid_mask)        valid_statistics = statistics[valid_mask]        valid_statistics_indexes = np.where(valid_mask)[0]        missing = np.arange(X.shape[not self.axis])[invalid_mask]        if self.axis == 0 and invalid_mask.any():            if self.verbose:                warnings.warn("Deleting features without "                              "observed values: %s" % missing)            X = X[:, valid_statistics_indexes]        elif self.axis == 1 and invalid_mask.any():            raise ValueError("Some rows only contain "                             "missing values: %s" % missing)        # Do actual imputation        if sparse.issparse(X) and self.missing_values != 0:            mask = _get_mask(X.data, self.missing_values)            indexes = np.repeat(np.arange(len(X.indptr) - 1, dtype=np.int),                                np.diff(X.indptr))[mask]            X.data[mask] = valid_statistics[indexes].astype(X.dtype,                                                            copy=False)        else:            if sparse.issparse(X):                X = X.toarray()            mask = _get_mask(X, self.missing_values)            n_missing = np.sum(mask, axis=self.axis)            values = np.repeat(valid_statistics, n_missing)            if self.axis == 0:                coordinates = np.where(mask.transpose())[::-1]            else:                coordinates = mask            X[coordinates] = values        return Xdiff --git a/sklearn/preprocessing/imputation.py b/sklearn/preprocessing/imputation.py-- a/sklearn/preprocessing/imputation.py++ b/sklearn/preprocessing/imputation.py


Question: Move imputation out of preprocessing While we're considering additional imputers, I've wondered whether preprocessing is the right place for it. Yes, it is a preprocessing step before other learning, but it often makes use of other supervised and unsupervised learners and hence is a learning task of its own. And preprocessing is getting a bit cramped. We could also do as with other models and have imputers appear in modules on the basis of how they work rather than function: could appear in neighbors for instance. could appear where..? And the basic in dummy? probably not. In practice I think it is more useful for users to , akin to our clusterers and decomposition, and unlike our predictors and outlier detectors that are grouped by algorithm.

from ..base import BaseEstimator, TransformerMixin from ..utils import check_array<ins>from ..utils import deprecated</ins> from ..utils.sparsefuncs import _get_median from ..utils.validation import check_is_fitted from ..utils.validation import FLOAT_DTYPES


Question: Move imputation out of preprocessing While we're considering additional imputers, I've wondered whether preprocessing is the right place for it. Yes, it is a preprocessing step before other learning, but it often makes use of other supervised and unsupervised learners and hence is a learning task of its own. And preprocessing is getting a bit cramped. We could also do as with other models and have imputers appear in modules on the basis of how they work rather than function: could appear in neighbors for instance. could appear where..? And the basic in dummy? probably not. In practice I think it is more useful for users to , akin to our clusterers and decomposition, and unlike our predictors and outlier detectors that are grouped by algorithm.

return extra_value  @deprecated("Imputer was deprecated in version 0.20 and will be "            "removed in 0.22. Import impute.SimpleImputer from "            "sklearn instead.") class Imputer(BaseEstimator, TransformerMixin):     """Imputation transformer for completing missing values. diff --git a/sklearn/utils/estimator_checks.py b/sklearn/utils/estimator_checks.py-- a/sklearn/utils/estimator_checks.py++ b/sklearn/utils/estimator_checks.py


Question: Move imputation out of preprocessing While we're considering additional imputers, I've wondered whether preprocessing is the right place for it. Yes, it is a preprocessing step before other learning, but it often makes use of other supervised and unsupervised learners and hence is a learning task of its own. And preprocessing is getting a bit cramped. We could also do as with other models and have imputers appear in modules on the basis of how they work rather than function: could appear in neighbors for instance. could appear where..? And the basic in dummy? probably not. In practice I think it is more useful for users to , akin to our clusterers and decomposition, and unlike our predictors and outlier detectors that are grouped by algorithm.

# cross-decomposition's "transform" returns X and Y         yield check_pipeline_consistency     if name not in ['Imputer']:    if name not in ['SimpleImputer', 'Imputer']:         # Test that all estimators check their input for NaN's and infs         yield check_estimators_nan_inf


Question: checkarray(X, dtype='numeric') should fail if X has strings Currently, dtype='numeric' is defined as "dtype is preserved unless is object". This seems overly lenient and strange behaviour, as in where shows that works without error and produces an array of strings! This behaviour is not tested and it's hard to believe that it is useful and intended. Perhaps we need a deprecation cycle, but I think dtype='numeric' should raise an error, or attempt to coerce, if the data does not actually have a numeric, real-valued dtype. checkarray(X, dtype='numeric') should fail if X has strings Currently, dtype='numeric' is defined as "dtype is preserved unless is object". This seems overly lenient and strange behaviour, as in where shows that works without error and produces an array of strings! This behaviour is not tested and it's hard to believe that it is useful and intended. Perhaps we need a deprecation cycle, but I think dtype='numeric' should raise an error, or attempt to coerce, if the data does not actually have a numeric, real-valued dtype.

# To ensure that array flags are maintained             array = np.array(array, dtype=dtype, order=order, copy=copy) <ins>        # in the future np.flexible dtypes will be handled like object dtypes        if dtype_numeric and np.issubdtype(array.dtype, np.flexible):            warnings.warn(                "Beginning in version 0.22, arrays of strings will be "                "interpreted as decimal numbers if parameter 'dtype' is "                "'numeric'. It is recommended that you convert the array to "                "type np.float64 before passing it to check_array.",                FutureWarning)</ins>         # make sure we actually converted to numeric:         if dtype_numeric and array.dtype.kind == "O":             array = array.astype(np.float64)


Question: LabelEncoder transform fails for empty lists (for certain inputs) Python 3.6.3, scikit_learn 0.19.1 Depending on which datatypes were used to fit the LabelEncoder, transforming empty lists works or not. Expected behavior would be that empty arrays are returned in both cases.

"""         check_is_fitted(self, 'classes_')         y = column_or_1d(y, warn=True)<ins>        # transform of empty array is empty array        if _num_samples(y) == 0:            return np.array([])</ins>          classes = np.unique(y)         if len(np.intersect1d(classes, self.classes_)) < len(classes):


Question: LabelEncoder transform fails for empty lists (for certain inputs) Python 3.6.3, scikit_learn 0.19.1 Depending on which datatypes were used to fit the LabelEncoder, transforming empty lists works or not. Expected behavior would be that empty arrays are returned in both cases.

y : numpy array of shape [n_samples]         """         check_is_fitted(self, 'classes_')<ins>        y = column_or_1d(y, warn=True)        # inverse transform of empty array is empty array        if _num_samples(y) == 0:            return np.array([])</ins>          diff = np.setdiff1d(y, np.arange(len(self.classes_)))         if len(diff):


Question: Deprecate Imputer with axis=1 After having tried to deal with a few issues related to extending behaviour, I believe we should be removing the parameter from . It seems a strange feature to support in a machine learning context, except perhaps where the features represent something like a time series. It is not stateful and can be performed with a FunctionTransformer. (We could even provide a function, if we felt it necessary, which would roughly be defined as .) It complicates the implementation, which already has a bunch of weird edge-cases (to handle sparse data with missing indicated by 0 which is an inefficient use of a sparse data structure; and to handle non-NaN missingness indicators), unnecessarily. It is often nonsensical to extend further features to the case. Do others agree? [MRG+1] Deprecate ` argument Deprecated the argument on the class.

X_missing[np.where(missing_samples)[0], missing_features] = 0 y_missing = y_full.copy() estimator = Pipeline([("imputer", Imputer(missing_values=0,                                          strategy="mean",                                          axis=0)),                                          strategy="mean")),                       ("forest", RandomForestRegressor(random_state=0,                                                        n_estimators=100))]) score = cross_val_score(estimator, X_missing, y_missing).mean()diff --git a/sklearn/preprocessing/imputation.py b/sklearn/preprocessing/imputation.py-- a/sklearn/preprocessing/imputation.py++ b/sklearn/preprocessing/imputation.py


Question: Deprecate Imputer with axis=1 After having tried to deal with a few issues related to extending behaviour, I believe we should be removing the parameter from . It seems a strange feature to support in a machine learning context, except perhaps where the features represent something like a time series. It is not stateful and can be performed with a FunctionTransformer. (We could even provide a function, if we felt it necessary, which would roughly be defined as .) It complicates the implementation, which already has a bunch of weird edge-cases (to handle sparse data with missing indicated by 0 which is an inefficient use of a sparse data structure; and to handle non-NaN missingness indicators), unnecessarily. It is often nonsensical to extend further features to the case. Do others agree? [MRG+1] Deprecate ` argument Deprecated the argument on the class.

- If "most_frequent", then replace missing using the most frequent           value along the axis.     axis : integer, optional (default=0)    axis : integer, optional (default=None)         The axis along which to impute.          - If `axis=0`, then impute along columns.         - If `axis=1`, then impute along rows.         .. deprecated:: 0.20           Parameter ``axis`` has been deprecated in 0.20 and will be removed           in 0.22. Future (and default) behavior is equivalent to ``axis=0``           (impute along columns). Row-wise imputation can be performed with           FunctionTransformer (e.g.,           ``FunctionTransformer(lambda X: Imputer().fit_transform(X.T).T)``).     verbose : integer, optional (default=0)         Controls the verbosity of the imputer.


Question: Deprecate Imputer with axis=1 After having tried to deal with a few issues related to extending behaviour, I believe we should be removing the parameter from . It seems a strange feature to support in a machine learning context, except perhaps where the features represent something like a time series. It is not stateful and can be performed with a FunctionTransformer. (We could even provide a function, if we felt it necessary, which would roughly be defined as .) It complicates the implementation, which already has a bunch of weird edge-cases (to handle sparse data with missing indicated by 0 which is an inefficient use of a sparse data structure; and to handle non-NaN missingness indicators), unnecessarily. It is often nonsensical to extend further features to the case. Do others agree? [MRG+1] Deprecate ` argument Deprecated the argument on the class.

contain missing values).     """     def __init__(self, missing_values="NaN", strategy="mean",                 axis=0, verbose=0, copy=True):                 axis=None, verbose=0, copy=True):         self.missing_values = missing_values         self.strategy = strategy         self.axis = axis