Talip7/scikit-learn-issues-multilabel huggingface dataset:
Add rolling window to sklearn.model_selection.TimeSeriesSplit

### Describe the workflow you want to enable

I wanted to ask whether any plans exist to implement a rolling/sliding window method in the TimeSeriesSplit class:

![68747470733a2f2f692e6962622e636f2f4b576b665137712f6e6577706c6f742e706e67](https://user-images.githubusercontent.com/28893120/154545460-d1629e8a-22a4-494d-affc-2df3cb95ade7.png)

 Currently, we are limited to using the expanding window type. For many financial time series models where a feature experiences a structural break, having a model whose weights are trained on the entire history can prove suboptimal.

I noted in https://github.com/scikit-learn/scikit-learn/pull/13204, specifically svenstehle's comments, that this might be on the horizon? 

### Describe your proposed solution

Current Implementation

```
>>> x = np.arange(15)
>>> cv = TimeSeriesSplit(n_splits=3, gap=2)
>>> for train_index, test_index in cv.split(x):
...      print("TRAIN:", train_index, "TEST:", test_index)
TRAIN: [0 1 2 3] TEST: [6 7 8]
TRAIN: [0 1 2 3 4 5 6] TEST: [ 9 10 11]
TRAIN: [0 1 2 3 4 5 6 7 8 9] TEST: [12 13 14]
```

Desired outcome

```
>>> x = np.arange(10)
>>> cv = TimeSeriesSplit(n_splits='walk_fw',  max_train_size=3, max_test_size=1)
>>> for train_index, test_index in cv.split(x):
...      print("TRAIN:", train_index, "TEST:", test_index)
TRAIN: [0 1 2] TEST: [3]
TRAIN: [1 2 3] TEST: [ 4]
TRAIN: [2 3 4] TEST: [5]
TRAIN: [ 3 4 5] TEST: [6]
TRAIN: [ 4 5 6] TEST: [7]
TRAIN: [ 5 6 7] TEST: [8]
TRAIN: [ 6 7 8] TEST: [9]
```

Where the 'stride' of the walk forward is proportionate to the test set, or walks by the max_train_size parameter?



### Describe alternatives you've considered, if relevant

_No response_

### Additional context

_No response_

COMMENT:
Currently there is rolling window support, where the train set does not grow:

```python
from sklearn.model_selection import TimeSeriesSplit

x = np.arange(15)
cv = TimeSeriesSplit(max_train_size=3, test_size=1)
for train_index, test_index in cv.split(x):
    print("TRAIN:", train_index, "TEST:", test_index)

# TRAIN: [7 8 9] TEST: [10]
# TRAIN: [ 8  9 10] TEST: [11]
# TRAIN: [ 9 10 11] TEST: [12]
# TRAIN: [10 11 12] TEST: [13]
# TRAIN: [11 12 13] TEST: [14]
```

If we want all the windows, we would need to adjust `n_splits` explicitly: 

```python
from sklearn.model_selection import TimeSeriesSplit

x = np.arange(15)
cv = TimeSeriesSplit(n_splits=12, max_train_size=3 ,test_size=1)
for train_index, test_index in cv.split(x):
    print("TRAIN:", train_index, "TEST:", test_index)

# TRAIN: [0 1 2] TEST: [3]
# TRAIN: [1 2 3] TEST: [4]
# TRAIN: [2 3 4] TEST: [5]
# TRAIN: [3 4 5] TEST: [6]
# TRAIN: [4 5 6] TEST: [7]
# TRAIN: [5 6 7] TEST: [8]
# TRAIN: [6 7 8] TEST: [9]
# TRAIN: [7 8 9] TEST: [10]
# TRAIN: [ 8  9 10] TEST: [11]
# TRAIN: [ 9 10 11] TEST: [12]
# TRAIN: [10 11 12] TEST: [13]
# TRAIN: [11 12 13] TEST: [14]
```

Is the proposal to have `n_splits='walk_fw'` provide all the windows automatically?

Labels: New Feature, module:model_selection
Add rolling window to sklearn.model_selection.TimeSeriesSplit

### Describe the workflow you want to enable

I wanted to ask whether any plans exist to implement a rolling/sliding window method in the TimeSeriesSplit class:

![68747470733a2f2f692e6962622e636f2f4b576b665137712f6e6577706c6f742e706e67](https://user-images.githubusercontent.com/28893120/154545460-d1629e8a-22a4-494d-affc-2df3cb95ade7.png)

 Currently, we are limited to using the expanding window type. For many financial time series models where a feature experiences a structural break, having a model whose weights are trained on the entire history can prove suboptimal.

I noted in https://github.com/scikit-learn/scikit-learn/pull/13204, specifically svenstehle's comments, that this might be on the horizon? 

### Describe your proposed solution

Current Implementation

```
>>> x = np.arange(15)
>>> cv = TimeSeriesSplit(n_splits=3, gap=2)
>>> for train_index, test_index in cv.split(x):
...      print("TRAIN:", train_index, "TEST:", test_index)
TRAIN: [0 1 2 3] TEST: [6 7 8]
TRAIN: [0 1 2 3 4 5 6] TEST: [ 9 10 11]
TRAIN: [0 1 2 3 4 5 6 7 8 9] TEST: [12 13 14]
```

Desired outcome

```
>>> x = np.arange(10)
>>> cv = TimeSeriesSplit(n_splits='walk_fw',  max_train_size=3, max_test_size=1)
>>> for train_index, test_index in cv.split(x):
...      print("TRAIN:", train_index, "TEST:", test_index)
TRAIN: [0 1 2] TEST: [3]
TRAIN: [1 2 3] TEST: [ 4]
TRAIN: [2 3 4] TEST: [5]
TRAIN: [ 3 4 5] TEST: [6]
TRAIN: [ 4 5 6] TEST: [7]
TRAIN: [ 5 6 7] TEST: [8]
TRAIN: [ 6 7 8] TEST: [9]
```

Where the 'stride' of the walk forward is proportionate to the test set, or walks by the max_train_size parameter?



### Describe alternatives you've considered, if relevant

_No response_

### Additional context

_No response_

COMMENT:
> Yes. Ideally, the `n_splits` parameter could be done away with? Therefore, the implementation reduces to how many observations are used in your rolling training window i.e. assuming daily observations, for a given financial time series, you could train a model on a rolling 252 day training window, and validate on a 63 day window, walking forward by the validation size.

So would you accept a PR where the `n_splits` field is removed as a parameter from the `TimeSeriesSplit(_BaseKFold)` class in the `scikit-learn/sklearn/model-selection/_split.py` file?

Something like this?
```
class TimeSeriesSplit(_BaseKFold):
  def __init__(self, *, max_train_size=None, test_size=None, gap=0):
          super().__init__(n_splits, shuffle=False, random_state=None)
          self.n_splits = 5
          self.max_train_size = max_train_size
          self.test_size = test_size
          self.gap = gap
```

Labels: New Feature, module:model_selection
Add rolling window to sklearn.model_selection.TimeSeriesSplit

### Describe the workflow you want to enable

I wanted to ask whether any plans exist to implement a rolling/sliding window method in the TimeSeriesSplit class:

![68747470733a2f2f692e6962622e636f2f4b576b665137712f6e6577706c6f742e706e67](https://user-images.githubusercontent.com/28893120/154545460-d1629e8a-22a4-494d-affc-2df3cb95ade7.png)

 Currently, we are limited to using the expanding window type. For many financial time series models where a feature experiences a structural break, having a model whose weights are trained on the entire history can prove suboptimal.

I noted in https://github.com/scikit-learn/scikit-learn/pull/13204, specifically svenstehle's comments, that this might be on the horizon? 

### Describe your proposed solution

Current Implementation

```
>>> x = np.arange(15)
>>> cv = TimeSeriesSplit(n_splits=3, gap=2)
>>> for train_index, test_index in cv.split(x):
...      print("TRAIN:", train_index, "TEST:", test_index)
TRAIN: [0 1 2 3] TEST: [6 7 8]
TRAIN: [0 1 2 3 4 5 6] TEST: [ 9 10 11]
TRAIN: [0 1 2 3 4 5 6 7 8 9] TEST: [12 13 14]
```

Desired outcome

```
>>> x = np.arange(10)
>>> cv = TimeSeriesSplit(n_splits='walk_fw',  max_train_size=3, max_test_size=1)
>>> for train_index, test_index in cv.split(x):
...      print("TRAIN:", train_index, "TEST:", test_index)
TRAIN: [0 1 2] TEST: [3]
TRAIN: [1 2 3] TEST: [ 4]
TRAIN: [2 3 4] TEST: [5]
TRAIN: [ 3 4 5] TEST: [6]
TRAIN: [ 4 5 6] TEST: [7]
TRAIN: [ 5 6 7] TEST: [8]
TRAIN: [ 6 7 8] TEST: [9]
```

Where the 'stride' of the walk forward is proportionate to the test set, or walks by the max_train_size parameter?



### Describe alternatives you've considered, if relevant

_No response_

### Additional context

_No response_

COMMENT:
We can not remove `n_splits` as it breaks backward compatibility and it has a real use case. We can enhance with a rolling window feature by having `n_split='walk_forward'`.

Labels: New Feature, module:model_selection
Add rolling window to sklearn.model_selection.TimeSeriesSplit

### Describe the workflow you want to enable

I wanted to ask whether any plans exist to implement a rolling/sliding window method in the TimeSeriesSplit class:

![68747470733a2f2f692e6962622e636f2f4b576b665137712f6e6577706c6f742e706e67](https://user-images.githubusercontent.com/28893120/154545460-d1629e8a-22a4-494d-affc-2df3cb95ade7.png)

 Currently, we are limited to using the expanding window type. For many financial time series models where a feature experiences a structural break, having a model whose weights are trained on the entire history can prove suboptimal.

I noted in https://github.com/scikit-learn/scikit-learn/pull/13204, specifically svenstehle's comments, that this might be on the horizon? 

### Describe your proposed solution

Current Implementation

```
>>> x = np.arange(15)
>>> cv = TimeSeriesSplit(n_splits=3, gap=2)
>>> for train_index, test_index in cv.split(x):
...      print("TRAIN:", train_index, "TEST:", test_index)
TRAIN: [0 1 2 3] TEST: [6 7 8]
TRAIN: [0 1 2 3 4 5 6] TEST: [ 9 10 11]
TRAIN: [0 1 2 3 4 5 6 7 8 9] TEST: [12 13 14]
```

Desired outcome

```
>>> x = np.arange(10)
>>> cv = TimeSeriesSplit(n_splits='walk_fw',  max_train_size=3, max_test_size=1)
>>> for train_index, test_index in cv.split(x):
...      print("TRAIN:", train_index, "TEST:", test_index)
TRAIN: [0 1 2] TEST: [3]
TRAIN: [1 2 3] TEST: [ 4]
TRAIN: [2 3 4] TEST: [5]
TRAIN: [ 3 4 5] TEST: [6]
TRAIN: [ 4 5 6] TEST: [7]
TRAIN: [ 5 6 7] TEST: [8]
TRAIN: [ 6 7 8] TEST: [9]
```

Where the 'stride' of the walk forward is proportionate to the test set, or walks by the max_train_size parameter?



### Describe alternatives you've considered, if relevant

_No response_

### Additional context

_No response_

COMMENT:
> 
So would setting `n_splits='walk_forward'` be equivalent to `n_splits=12`? Or is it more complex than this?

I ask because as you mentioned, rolling window support is already included, just not for all windows. 
The way I see it `n_splits='walk_forward' == n_splits='12'` and setting `n_splits=12` should include all windows right?
For example:
```
x = np.arange(15)
cv = TimeSeriesSplit(n_splits='walk_forward', max_train_size=3 ,test_size=1)
for train_index, test_index in cv.split(x):
    print("TRAIN:", train_index, "TEST:", test_index)

# TRAIN: [0 1 2] TEST: [3]
# TRAIN: [1 2 3] TEST: [4]
# TRAIN: [2 3 4] TEST: [5]
# TRAIN: [3 4 5] TEST: [6]
# TRAIN: [4 5 6] TEST: [7]
# TRAIN: [5 6 7] TEST: [8]
# TRAIN: [6 7 8] TEST: [9]
# TRAIN: [7 8 9] TEST: [10]
# TRAIN: [ 8  9 10] TEST: [11]
# TRAIN: [ 9 10 11] TEST: [12]
# TRAIN: [10 11 12] TEST: [13]
# TRAIN: [11 12 13] TEST: [14]
``` 


> We can not remove `n_splits` as it breaks backward compatibility and it has a real use case. We can enhance with a rolling window feature by having `n_split='walk_forward'`.

Labels: New Feature, module:model_selection
Add rolling window to sklearn.model_selection.TimeSeriesSplit

### Describe the workflow you want to enable

I wanted to ask whether any plans exist to implement a rolling/sliding window method in the TimeSeriesSplit class:

![68747470733a2f2f692e6962622e636f2f4b576b665137712f6e6577706c6f742e706e67](https://user-images.githubusercontent.com/28893120/154545460-d1629e8a-22a4-494d-affc-2df3cb95ade7.png)

 Currently, we are limited to using the expanding window type. For many financial time series models where a feature experiences a structural break, having a model whose weights are trained on the entire history can prove suboptimal.

I noted in https://github.com/scikit-learn/scikit-learn/pull/13204, specifically svenstehle's comments, that this might be on the horizon? 

### Describe your proposed solution

Current Implementation

```
>>> x = np.arange(15)
>>> cv = TimeSeriesSplit(n_splits=3, gap=2)
>>> for train_index, test_index in cv.split(x):
...      print("TRAIN:", train_index, "TEST:", test_index)
TRAIN: [0 1 2 3] TEST: [6 7 8]
TRAIN: [0 1 2 3 4 5 6] TEST: [ 9 10 11]
TRAIN: [0 1 2 3 4 5 6 7 8 9] TEST: [12 13 14]
```

Desired outcome

```
>>> x = np.arange(10)
>>> cv = TimeSeriesSplit(n_splits='walk_fw',  max_train_size=3, max_test_size=1)
>>> for train_index, test_index in cv.split(x):
...      print("TRAIN:", train_index, "TEST:", test_index)
TRAIN: [0 1 2] TEST: [3]
TRAIN: [1 2 3] TEST: [ 4]
TRAIN: [2 3 4] TEST: [5]
TRAIN: [ 3 4 5] TEST: [6]
TRAIN: [ 4 5 6] TEST: [7]
TRAIN: [ 5 6 7] TEST: [8]
TRAIN: [ 6 7 8] TEST: [9]
```

Where the 'stride' of the walk forward is proportionate to the test set, or walks by the max_train_size parameter?



### Describe alternatives you've considered, if relevant

_No response_

### Additional context

_No response_

COMMENT:
> The way I see it n_splits='walk_forward' == n_splits='12' and setting n_splits=12 should include all windows right?

`n_split=12` only works when `max_train_size=3`, `test_size=1` and `X.shape[0]=15`.

For example, if `max_train_size=10` and `test_size=2`, then `n_splits` need to be set to 4 to properly walk forward:

```python
x = np.arange(15)
cv = TimeSeriesSplit(n_splits=4, max_train_size=10,test_size=1)
for train_index, test_index in cv.split(x):
    print("TRAIN:", train_index, "TEST:", test_index)
``` 

`n_split="walk_forward"` would automatically compute the proper value of `n_splits` based on `X.shape[0]`, `test_size` and `max_train_size`.

Labels: New Feature, module:model_selection
Add rolling window to sklearn.model_selection.TimeSeriesSplit

### Describe the workflow you want to enable

I wanted to ask whether any plans exist to implement a rolling/sliding window method in the TimeSeriesSplit class:

![68747470733a2f2f692e6962622e636f2f4b576b665137712f6e6577706c6f742e706e67](https://user-images.githubusercontent.com/28893120/154545460-d1629e8a-22a4-494d-affc-2df3cb95ade7.png)

 Currently, we are limited to using the expanding window type. For many financial time series models where a feature experiences a structural break, having a model whose weights are trained on the entire history can prove suboptimal.

I noted in https://github.com/scikit-learn/scikit-learn/pull/13204, specifically svenstehle's comments, that this might be on the horizon? 

### Describe your proposed solution

Current Implementation

```
>>> x = np.arange(15)
>>> cv = TimeSeriesSplit(n_splits=3, gap=2)
>>> for train_index, test_index in cv.split(x):
...      print("TRAIN:", train_index, "TEST:", test_index)
TRAIN: [0 1 2 3] TEST: [6 7 8]
TRAIN: [0 1 2 3 4 5 6] TEST: [ 9 10 11]
TRAIN: [0 1 2 3 4 5 6 7 8 9] TEST: [12 13 14]
```

Desired outcome

```
>>> x = np.arange(10)
>>> cv = TimeSeriesSplit(n_splits='walk_fw',  max_train_size=3, max_test_size=1)
>>> for train_index, test_index in cv.split(x):
...      print("TRAIN:", train_index, "TEST:", test_index)
TRAIN: [0 1 2] TEST: [3]
TRAIN: [1 2 3] TEST: [ 4]
TRAIN: [2 3 4] TEST: [5]
TRAIN: [ 3 4 5] TEST: [6]
TRAIN: [ 4 5 6] TEST: [7]
TRAIN: [ 5 6 7] TEST: [8]
TRAIN: [ 6 7 8] TEST: [9]
```

Where the 'stride' of the walk forward is proportionate to the test set, or walks by the max_train_size parameter?



### Describe alternatives you've considered, if relevant

_No response_

### Additional context

_No response_

COMMENT:
Hi, what is the status of this? This feature would be very useful. @msat59's code seems to work for me.

Labels: New Feature, module:model_selection
Add rolling window to sklearn.model_selection.TimeSeriesSplit

### Describe the workflow you want to enable

I wanted to ask whether any plans exist to implement a rolling/sliding window method in the TimeSeriesSplit class:

![68747470733a2f2f692e6962622e636f2f4b576b665137712f6e6577706c6f742e706e67](https://user-images.githubusercontent.com/28893120/154545460-d1629e8a-22a4-494d-affc-2df3cb95ade7.png)

 Currently, we are limited to using the expanding window type. For many financial time series models where a feature experiences a structural break, having a model whose weights are trained on the entire history can prove suboptimal.

I noted in https://github.com/scikit-learn/scikit-learn/pull/13204, specifically svenstehle's comments, that this might be on the horizon? 

### Describe your proposed solution

Current Implementation

```
>>> x = np.arange(15)
>>> cv = TimeSeriesSplit(n_splits=3, gap=2)
>>> for train_index, test_index in cv.split(x):
...      print("TRAIN:", train_index, "TEST:", test_index)
TRAIN: [0 1 2 3] TEST: [6 7 8]
TRAIN: [0 1 2 3 4 5 6] TEST: [ 9 10 11]
TRAIN: [0 1 2 3 4 5 6 7 8 9] TEST: [12 13 14]
```

Desired outcome

```
>>> x = np.arange(10)
>>> cv = TimeSeriesSplit(n_splits='walk_fw',  max_train_size=3, max_test_size=1)
>>> for train_index, test_index in cv.split(x):
...      print("TRAIN:", train_index, "TEST:", test_index)
TRAIN: [0 1 2] TEST: [3]
TRAIN: [1 2 3] TEST: [ 4]
TRAIN: [2 3 4] TEST: [5]
TRAIN: [ 3 4 5] TEST: [6]
TRAIN: [ 4 5 6] TEST: [7]
TRAIN: [ 5 6 7] TEST: [8]
TRAIN: [ 6 7 8] TEST: [9]
```

Where the 'stride' of the walk forward is proportionate to the test set, or walks by the max_train_size parameter?



### Describe alternatives you've considered, if relevant

_No response_

### Additional context

_No response_

COMMENT:
Any updates?

Labels: New Feature, module:model_selection
Tolerane parameter definiton in KMeans

### Describe the issue linked to the documentation

KMeans documentation says:

> tol - Relative tolerance with regards to Frobenius norm of the difference in the cluster centers of two consecutive iterations to declare convergence.

But if we look into the code for stopping criterion (both in _kmeans_single_lloyd and _kmeans_single_elkan) we can see:
>                center_shift_tot = (center_shift ** 2).sum()
>                if center_shift_tot <= tol:

So it seems that stopping criterion is **nominal/direct** tolerance with regards to Frobenius norm instead of **relative**? Or maybe I am misinterpreting the code?


### Suggest a potential alternative/fix

_No response_

COMMENT:
Actually at this point, tol doesn't have the same value that you passed to the constructor. It's scaled by the variance of the data to be ``self._tol = np.mean(np.var(X, axis=0)) * tol``.

So in the end the stopping criterion is
``(center_shift ** 2).sum() / np.mean(np.var(X, axis=0)) <= tol``
which can be considered a relative difference. relative being relative to the scale of the data.

I'd rather have it be
``(center_shift ** 2).sum() / (centers ** 2).sum() <= tol``
or even be the average relative center shift
``((center_shift ** 2).sum(axis=1) / (centers ** 2).sum(axis=1)).mean() <= tol``
but it does not make a huge difference, the important thing being that the center_shift is scaled by something that scales with the data.

Labels: Documentation, module:cluster
Tolerane parameter definiton in KMeans

### Describe the issue linked to the documentation

KMeans documentation says:

> tol - Relative tolerance with regards to Frobenius norm of the difference in the cluster centers of two consecutive iterations to declare convergence.

But if we look into the code for stopping criterion (both in _kmeans_single_lloyd and _kmeans_single_elkan) we can see:
>                center_shift_tot = (center_shift ** 2).sum()
>                if center_shift_tot <= tol:

So it seems that stopping criterion is **nominal/direct** tolerance with regards to Frobenius norm instead of **relative**? Or maybe I am misinterpreting the code?


### Suggest a potential alternative/fix

_No response_

COMMENT:
I see. But if relative is referring to the scale of data, doesn't it mean that the part of description "...of two consecutive iterations..." is wrong? Like you wrote - I would expect something like:
`(center_shift ** 2).sum() / (centers ** 2).sum() <= tol`

But the fact of scaling which come up is another confusing issue. The same effect (stopping with regard of scaled data) can be achieved just by putting into an algorithm scaled data. I'm not sure, but isn't scaling by variance performed in KMean in some way inconsistent with the scikit-learn's rule of separating operations on data and modeling? In this approach distances between observations are calculated on raw data but stopping criterion is referring to scaled data - it looks strange to me. And even though somebody puts into algorithm unscaled data intentionally, the stopping criterion will use scaling and it is impossible to turn it off. 
Additionally, if we look (as you wrote and I think it would be more appropriate) at:
`(center_shift ** 2).sum() / (centers ** 2).sum() <= tol`
then scaling by variance could be definitely skipped.

Labels: Documentation, module:cluster
Tolerane parameter definiton in KMeans

### Describe the issue linked to the documentation

KMeans documentation says:

> tol - Relative tolerance with regards to Frobenius norm of the difference in the cluster centers of two consecutive iterations to declare convergence.

But if we look into the code for stopping criterion (both in _kmeans_single_lloyd and _kmeans_single_elkan) we can see:
>                center_shift_tot = (center_shift ** 2).sum()
>                if center_shift_tot <= tol:

So it seems that stopping criterion is **nominal/direct** tolerance with regards to Frobenius norm instead of **relative**? Or maybe I am misinterpreting the code?


### Suggest a potential alternative/fix

_No response_

COMMENT:
I agree. I guess the original intention was to have a ``tol`` parameter independant of the scale of the data such that the default value would be reasonable in most cases. 
I also agree that this formulation ``(center_shift ** 2).sum() / (centers ** 2).sum() <= tol`` does not suffer from scaling and to me it should be preferred.

If you're interested, feel free to open a PR to change the behavior to really be the relative center shift. I would support it. It should be done in KMeans and MiniBatchKMeans. However we usually don't want do change existing behavior directly but go through a deprecation cycle instead. Unless we consider the current behavior to be a bug.

> And even though somebody puts into algorithm unscaled data intentionally, the stopping criterion will use scaling and it is impossible to turn it off

If you really want to unscale tol it's possible. You'd have to pass tol=your_tol / mean(var(X)) to KMeans. Not ideal though.

Labels: Documentation, module:cluster
Add new feature to use only a sample of training data in KNNImputer

### Describe the workflow you want to enable

I would like the team to add an argument(s) for using only part of the entire dataset to train the KNNImputer.

### Describe your proposed solution

This will require adding new argument(s) to the KNNImputer that allows the user to train the imputer with only part of the training data. This will save a significant amount of time as the current version takes too long and is almost not usable for fairly large training data.

The proposed solution runs orders of magnitude faster than using the whole dataset and may give higher accuracy than using constant imputation.

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

_No response_

### Additional context

imputer = KNNImputer()
imputer.fit(df)
df_new = imputer.transform(df) # This takes a very long time if dataset is fairly large

### What the proposed solution may look like
imputer = KNNImputer(sample=1000, random_state=None)
imputer.fit(df) # Uses only a thousand samples to train the imputer
df_new = imputer.transform(df) # Runs orders of magnitude faster than using the whole dataset.

COMMENT:
This seems reasonable to do. scikit-learn does not usually include techniques unless it is backed by another source. Do you have a reference such as a paper that looks into sampling the training set for KNN imputing?

Labels: New Feature, module:impute