Repository: feature-engine/feature_engine
Pull request #582 (2023-01-07 03:15:03)

Adding Examples for Feature Selection Module
Hi @solegalli ,

Happy New Year, please review the added examples for all the Feature Selection Methods.

PS: Would you check why tests are failing, I think it is not related to my code.

solegalli: Hey @datacubeR 

tests have now been fixed in #583 

If you rebase main onto your feature-branch, that should do it.
datacubeR: Hi @solegalli. 
Sorry for the delay but I fixed all the suggestions given above and pass all the tests. 
Let me know if everything is OK.

Thanks.

Alfonso
codecov[bot]: # [Codecov](https://codecov.io/gh/feature-engine/feature_engine/pull/582?src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=feature-engine) Report
> Merging [#582](https://codecov.io/gh/feature-engine/feature_engine/pull/582?src=pr&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=feature-engine) (dcb2b59) into [main](https://codecov.io/gh/feature-engine/feature_engine/commit/31f621536481443e7adae47dda3f5ee0d626ac8b?el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=feature-engine) (31f6215) will **not change** coverage.
> The diff coverage is `n/a`.

```diff
@@           Coverage Diff           @@
##             main     #582   +/-   ##
=======================================
  Coverage   97.89%   97.89%           
=======================================
  Files          95       95           
  Lines        3559     3559           
  Branches      688      688           
=======================================
  Hits         3484     3484           
  Misses         28       28           
  Partials       47       47           
```


| [Impacted Files](https://codecov.io/gh/feature-engine/feature_engine/pull/582?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=feature-engine) | Coverage Δ | |
|---|---|---|
| [feature\_engine/selection/drop\_constant\_features.py](https://codecov.io/gh/feature-engine/feature_engine/pull/582?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=feature-engine#diff-ZmVhdHVyZV9lbmdpbmUvc2VsZWN0aW9uL2Ryb3BfY29uc3RhbnRfZmVhdHVyZXMucHk=) | `100.00% <ø> (ø)` | |
| [...ature\_engine/selection/drop\_correlated\_features.py](https://codecov.io/gh/feature-engine/feature_engine/pull/582?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=feature-engine#diff-ZmVhdHVyZV9lbmdpbmUvc2VsZWN0aW9uL2Ryb3BfY29ycmVsYXRlZF9mZWF0dXJlcy5weQ==) | `90.00% <ø> (ø)` | |
| [...eature\_engine/selection/drop\_duplicate\_features.py](https://codecov.io/gh/feature-engine/feature_engine/pull/582?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=feature-engine#diff-ZmVhdHVyZV9lbmdpbmUvc2VsZWN0aW9uL2Ryb3BfZHVwbGljYXRlX2ZlYXR1cmVzLnB5) | `96.07% <ø> (ø)` | |
| [feature\_engine/selection/drop\_features.py](https://codecov.io/gh/feature-engine/feature_engine/pull/582?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=feature-engine#diff-ZmVhdHVyZV9lbmdpbmUvc2VsZWN0aW9uL2Ryb3BfZmVhdHVyZXMucHk=) | `100.00% <ø> (ø)` | |
| [feature\_engine/selection/drop\_psi\_features.py](https://codecov.io/gh/feature-engine/feature_engine/pull/582?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=feature-engine#diff-ZmVhdHVyZV9lbmdpbmUvc2VsZWN0aW9uL2Ryb3BfcHNpX2ZlYXR1cmVzLnB5) | `98.31% <ø> (ø)` | |
| [feature\_engine/selection/information\_value.py](https://codecov.io/gh/feature-engine/feature_engine/pull/582?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=feature-engine#diff-ZmVhdHVyZV9lbmdpbmUvc2VsZWN0aW9uL2luZm9ybWF0aW9uX3ZhbHVlLnB5) | `100.00% <ø> (ø)` | |
| [...ure\_engine/selection/recursive\_feature\_addition.py](https://codecov.io/gh/feature-engine/feature_engine/pull/582?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=feature-engine#diff-ZmVhdHVyZV9lbmdpbmUvc2VsZWN0aW9uL3JlY3Vyc2l2ZV9mZWF0dXJlX2FkZGl0aW9uLnB5) | `100.00% <ø> (ø)` | |
| [...\_engine/selection/recursive\_feature\_elimination.py](https://codecov.io/gh/feature-engine/feature_engine/pull/582?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=feature-engine#diff-ZmVhdHVyZV9lbmdpbmUvc2VsZWN0aW9uL3JlY3Vyc2l2ZV9mZWF0dXJlX2VsaW1pbmF0aW9uLnB5) | `93.54% <ø> (ø)` | |
| [feature\_engine/selection/shuffle\_features.py](https://codecov.io/gh/feature-engine/feature_engine/pull/582?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=feature-engine#diff-ZmVhdHVyZV9lbmdpbmUvc2VsZWN0aW9uL3NodWZmbGVfZmVhdHVyZXMucHk=) | `100.00% <ø> (ø)` | |
| [...ure\_engine/selection/single\_feature\_performance.py](https://codecov.io/gh/feature-engine/feature_engine/pull/582?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=feature-engine#diff-ZmVhdHVyZV9lbmdpbmUvc2VsZWN0aW9uL3NpbmdsZV9mZWF0dXJlX3BlcmZvcm1hbmNlLnB5) | `100.00% <ø> (ø)` | |
| ... and [2 more](https://codecov.io/gh/feature-engine/feature_engine/pull/582?src=pr&el=tree-more&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=feature-engine) | |

:mega: We’re building smart automated test selection to slash your CI/CD build times. [Learn more](https://about.codecov.io/iterative-testing/?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=feature-engine)


Patch:
diff --git a/docs/api_doc/datetime/index.rst b/docs/api_doc/datetime/index.rst
index c47d463..c30432a 100644
--- a/docs/api_doc/datetime/index.rst
+++ b/docs/api_doc/datetime/index.rst
@@ -7,7 +7,7 @@ Feature-engine's datetime transformers are able to extract a wide variety of dat
 features from existing datetime or object-like data.
 
 .. toctree::
-   :maxdepth: 2
+   :maxdepth: 1
 
    DatetimeFeatures
 
diff --git a/docs/api_doc/discretisation/index.rst b/docs/api_doc/discretisation/index.rst
index 5c181ae..75c484e 100644
--- a/docs/api_doc/discretisation/index.rst
+++ b/docs/api_doc/discretisation/index.rst
@@ -22,7 +22,7 @@ into continuous intervals.
 
 
 .. toctree::
-   :maxdepth: 2
+   :maxdepth: 1
    :hidden:
 
    EqualFrequencyDiscretiser
diff --git a/docs/api_doc/imputation/index.rst b/docs/api_doc/imputation/index.rst
index aba52b3..8a1a95e 100644
--- a/docs/api_doc/imputation/index.rst
+++ b/docs/api_doc/imputation/index.rst
@@ -30,7 +30,7 @@ categorical variables by nature are coded as numeric.
 
 
 .. toctree::
-   :maxdepth: 2
+   :maxdepth: 1
    :hidden:
 
    MeanMedianImputer
diff --git a/docs/api_doc/index.rst b/docs/api_doc/index.rst
index c9b26ba..fce823e 100644
--- a/docs/api_doc/index.rst
+++ b/docs/api_doc/index.rst
@@ -50,3 +50,11 @@ Other
 
    preprocessing/index
    wrappers/index
+
+
+Tools
+-----
+.. toctree::
+   :maxdepth: 1
+
+   variable_handling/index
\ No newline at end of file
diff --git a/docs/api_doc/outliers/index.rst b/docs/api_doc/outliers/index.rst
index 556e447..49abef0 100644
--- a/docs/api_doc/outliers/index.rst
+++ b/docs/api_doc/outliers/index.rst
@@ -17,7 +17,7 @@ arbitrary or derived value. The OutlierTrimmer removes outliers from the dataset
 =================================== ==============================================================
 
 .. toctree::
-   :maxdepth: 2
+   :maxdepth: 1
    :hidden:
 
    Winsorizer
diff --git a/docs/api_doc/selection/index.rst b/docs/api_doc/selection/index.rst
index b17b33c..9e0dfdc 100644
--- a/docs/api_doc/selection/index.rst
+++ b/docs/api_doc/selection/index.rst
@@ -63,7 +63,7 @@ Alternative feature selection methods
 
 
 .. toctree::
-   :maxdepth: 2
+   :maxdepth: 1
    :hidden:
 
    DropFeatures
diff --git a/docs/api_doc/timeseries/forecasting/index.rst b/docs/api_doc/timeseries/forecasting/index.rst
index 8670589..99f95c5 100644
--- a/docs/api_doc/timeseries/forecasting/index.rst
+++ b/docs/api_doc/timeseries/forecasting/index.rst
@@ -8,7 +8,7 @@ dataframe by lagging features or calculating statistics over windows of time in
 past.
 
 .. toctree::
-   :maxdepth: 2
+   :maxdepth: 1
 
    LagFeatures
    WindowFeatures
diff --git a/docs/api_doc/timeseries/index.rst b/docs/api_doc/timeseries/index.rst
index cdae20a..70370fc 100644
--- a/docs/api_doc/timeseries/index.rst
+++ b/docs/api_doc/timeseries/index.rst
@@ -6,7 +6,7 @@ Time Series Features
 Feature-engine's time series transformers derive features from time series data.
 
 .. toctree::
-   :maxdepth: 2
+   :maxdepth: 1
 
    forecasting/index
 
diff --git a/docs/api_doc/transformation/index.rst b/docs/api_doc/transformation/index.rst
index 543c073..0705f4d 100644
--- a/docs/api_doc/transformation/index.rst
+++ b/docs/api_doc/transformation/index.rst
@@ -7,7 +7,7 @@ Feature-engine's variable transformers transform numerical variables with variou
 mathematical transformations.
 
 .. toctree::
-   :maxdepth: 2
+   :maxdepth: 1
 
    LogTransformer
    LogCpTransformer
diff --git a/docs/api_doc/variable_handling/find_all_variables.rst b/docs/api_doc/variable_handling/find_all_variables.rst
new file mode 100644
index 0000000..e80091d
--- /dev/null
+++ b/docs/api_doc/variable_handling/find_all_variables.rst
@@ -0,0 +1,6 @@
+﻿find_all_variables
+==================
+
+.. currentmodule:: feature_engine.variable_handling
+
+.. autofunction:: find_all_variables
\ No newline at end of file
diff --git a/docs/api_doc/variable_handling/find_categorical_and_numerical_variables.rst b/docs/api_doc/variable_handling/find_categorical_and_numerical_variables.rst
new file mode 100644
index 0000000..8712a5e
--- /dev/null
+++ b/docs/api_doc/variable_handling/find_categorical_and_numerical_variables.rst
@@ -0,0 +1,6 @@
+﻿find_categorical_and_numerical_variables
+========================================
+
+.. currentmodule:: feature_engine.variable_handling
+
+.. autofunction:: find_categorical_and_numerical_variables
\ No newline at end of file
diff --git a/docs/api_doc/variable_handling/find_or_check_categorical_variables.rst b/docs/api_doc/variable_handling/find_or_check_categorical_variables.rst
new file mode 100644
index 0000000..5013573
--- /dev/null
+++ b/docs/api_doc/variable_handling/find_or_check_categorical_variables.rst
@@ -0,0 +1,6 @@
+﻿find_or_check_categorical_variables
+===================================
+
+.. currentmodule:: feature_engine.variable_handling
+
+.. autofunction:: find_or_check_categorical_variables
\ No newline at end of file
diff --git a/docs/api_doc/variable_handling/find_or_check_datetime_variables.rst b/docs/api_doc/variable_handling/find_or_check_datetime_variables.rst
new file mode 100644
index 0000000..53a86ce
--- /dev/null
+++ b/docs/api_doc/variable_handling/find_or_check_datetime_variables.rst
@@ -0,0 +1,6 @@
+﻿find_or_check_datetime_variables
+================================
+
+.. currentmodule:: feature_engine.variable_handling
+
+.. autofunction:: find_or_check_datetime_variables
\ No newline at end of file
diff --git a/docs/api_doc/variable_handling/find_or_check_numerical_variables.rst b/docs/api_doc/variable_handling/find_or_check_numerical_variables.rst
new file mode 100644
index 0000000..767eaf7
--- /dev/null
+++ b/docs/api_doc/variable_handling/find_or_check_numerical_variables.rst
@@ -0,0 +1,6 @@
+﻿find_or_check_numerical_variables
+=================================
+
+.. currentmodule:: feature_engine.variable_handling
+
+.. autofunction:: find_or_check_numerical_variables
\ No newline at end of file
diff --git a/docs/api_doc/variable_handling/index.rst b/docs/api_doc/variable_handling/index.rst
new file mode 100644
index 0000000..83cb744
--- /dev/null
+++ b/docs/api_doc/variable_handling/index.rst
@@ -0,0 +1,25 @@
+.. -*- mode: rst -*-
+
+Variable handling functions
+===========================
+
+Feature-engine functions for finding variables of a specific type or ensuring that the
+variables are of the correct type.
+
+The functions take a dataframe as an argument and return the names of the variables in
+the desired type.
+
+You can also pass a dataframe with a list of variables to check if they are all of the
+desired type.
+
+These functions are used under the hood by all Feature-engine transformers to select the
+variables that they will modify or operate with.
+
+.. toctree::
+   :maxdepth: 1
+
+   find_all_variables
+   find_categorical_and_numerical_variables
+   find_or_check_categorical_variables
+   find_or_check_datetime_variables
+   find_or_check_numerical_variables
diff --git a/docs/api_doc/wrappers/index.rst b/docs/api_doc/wrappers/index.rst
index 9de7236..98a4735 100644
--- a/docs/api_doc/wrappers/index.rst
+++ b/docs/api_doc/wrappers/index.rst
@@ -9,7 +9,7 @@ Feature-engine's Scikit-learn wrappers wrap Scikit-learn transformers allowing t
 implementation only on a selected subset of features.
 
 .. toctree::
-   :maxdepth: 2
+   :maxdepth: 1
 
    Wrapper
 
diff --git a/docs/user_guide/index.rst b/docs/user_guide/index.rst
index 790c846..2cb029d 100644
--- a/docs/user_guide/index.rst
+++ b/docs/user_guide/index.rst
@@ -53,3 +53,11 @@ Other
 
    preprocessing/index
    wrappers/index
+
+
+Tools
+-----
+.. toctree::
+   :maxdepth: 1
+
+   variable_handling/index
\ No newline at end of file
diff --git a/docs/user_guide/timeseries/index.rst b/docs/user_guide/timeseries/index.rst
index 1d719a4..9d40cae 100644
--- a/docs/user_guide/timeseries/index.rst
+++ b/docs/user_guide/timeseries/index.rst
@@ -10,7 +10,7 @@ Time Series Features
 Feature-engine's time series transformers create features from time series data.
 
 .. toctree::
-   :maxdepth: 2
+   :maxdepth: 1
 
    forecasting/index
 
diff --git a/docs/user_guide/variable_handling/find_all_variables.rst b/docs/user_guide/variable_handling/find_all_variables.rst
new file mode 100644
index 0000000..eac33d4
--- /dev/null
+++ b/docs/user_guide/variable_handling/find_all_variables.rst
@@ -0,0 +1,133 @@
+﻿.. _find_all_vars:
+
+.. currentmodule:: feature_engine.variable_handling.variable_type_selection
+
+find_all_variables
+==================
+
+With :class:`find_all_variables()` you can automatically capture in a list the names of
+all the variables in the dataset.
+
+Let's create a toy dataset with numerical, categorical and datetime variables:
+
+.. code:: python
+
+    import pandas as pd
+    from sklearn.datasets import make_classification
+
+    X, y = make_classification(
+        n_samples=1000,
+        n_features=4,
+        n_redundant=1,
+        n_clusters_per_class=1,
+        weights=[0.50],
+        class_sep=2,
+        random_state=1,
+    )
+
+    # transform arrays into pandas df and series
+    colnames = [f"num_var_{i+1}" for i in range(4)]
+    X = pd.DataFrame(X, columns=colnames)
+
+    X["cat_var1"] = ["Hello"] * 1000
+    X["cat_var2"] = ["Bye"] * 1000
+
+    X["date1"] = pd.date_range("2020-02-24", periods=1000, freq="T")
+    X["date2"] = pd.date_range("2021-09-29", periods=1000, freq="H")
+    X["date3"] = ["2020-02-24"] * 1000
+
+    print(X.head())
+
+We see the resulting dataframe below:
+
+.. code:: python
+
+       num_var_1  num_var_2  num_var_3  num_var_4 cat_var1 cat_var2  \
+    0  -1.558594   1.634123   1.556932   2.869318    Hello      Bye
+    1   1.499925   1.651008   1.159977   2.510196    Hello      Bye
+    2   0.277127  -0.263527   0.532159   0.274491    Hello      Bye
+    3  -1.139190  -1.131193   2.296540   1.189781    Hello      Bye
+    4  -0.530061  -2.280109   2.469580   0.365617    Hello      Bye
+
+                    date1               date2       date3
+    0 2020-02-24 00:00:00 2021-09-29 00:00:00  2020-02-24
+    1 2020-02-24 00:01:00 2021-09-29 01:00:00  2020-02-24
+    2 2020-02-24 00:02:00 2021-09-29 02:00:00  2020-02-24
+    3 2020-02-24 00:03:00 2021-09-29 03:00:00  2020-02-24
+    4 2020-02-24 00:04:00 2021-09-29 04:00:00  2020-02-24
+
+We can now use :class:`find_all_variables()` to capture all the variable names in a list.
+So let's do that and then display the items in the list:
+
+.. code:: python
+
+    from feature_engine.variable_handling import find_all_variables
+
+    vars_all = find_all_variables(X)
+
+    vars_all
+
+We see the variable names in the list below:
+
+.. code:: python
+
+    ['num_var_1',
+     'num_var_2',
+     'num_var_3',
+     'num_var_4',
+     'cat_var1',
+     'cat_var2',
+     'date1',
+     'date2',
+     'date3']
+
+We have the option to return the name of the variables of type categorical, object and
+numerical only, or in other words, to exclude datetime variables. We can do so as
+follows:
+
+.. code:: python
+
+    vars_all = find_all_variables(X, exclude_datetime=True)
+
+    vars_all
+
+In the list below, we can see that variables of type datetime were ignored:
+
+.. code:: python
+
+    ['num_var_1',
+     'num_var_2',
+     'num_var_3',
+     'num_var_4',
+     'cat_var1',
+     'cat_var2',
+     'date3']
+
+
+We can also use :class:`find_all_variables()` with a list of variable names. It will
+corroborate that the variables indicated in the list are in the dataframe.
+
+.. code:: python
+
+    vars_all = find_all_variables(X, ["num_var_1", "cat_var1", "date1"])
+
+    vars_all
+
+The output is the list of variable names passed to the function:
+
+.. code:: python
+
+    ['num_var_1', 'cat_var1', 'date1']
+
+If we pass the name of a variable that is not in the dataframe, :class:`find_all_variables()`
+will return an error:
+
+.. code:: python
+
+    find_all_variables(X, ["hola", "cat_var1", "date1"])
+
+Below we see the error message:
+
+.. code:: python
+
+    KeyError: 'Some of the variables are not in the dataframe.'
\ No newline at end of file
diff --git a/docs/user_guide/variable_handling/find_categorical_and_numerical_variables.rst b/docs/user_guide/variable_handling/find_categorical_and_numerical_variables.rst
new file mode 100644
index 0000000..f485173
--- /dev/null
+++ b/docs/user_guide/variable_handling/find_categorical_and_numerical_variables.rst
@@ -0,0 +1,105 @@
+﻿.. _find_cat_and_num_vars:
+
+.. currentmodule:: feature_engine.variable_handling.variable_type_selection
+
+find_categorical_and_numerical_variables
+========================================
+
+With :class:`find_categorical_and_numerical_variables()` you can automatically capture in
+2 separate lists the names of all the categorical and numerical variables in the dataset,
+respectively.
+
+Let's create a toy dataset with numerical, categorical and datetime variables:
+
+.. code:: python
+
+    import pandas as pd
+    from sklearn.datasets import make_classification
+
+    X, y = make_classification(
+        n_samples=1000,
+        n_features=4,
+        n_redundant=1,
+        n_clusters_per_class=1,
+        weights=[0.50],
+        class_sep=2,
+        random_state=1,
+    )
+
+    # transform arrays into pandas df and series
+    colnames = [f"num_var_{i+1}" for i in range(4)]
+    X = pd.DataFrame(X, columns=colnames)
+
+    X["cat_var1"] = ["Hello"] * 1000
+    X["cat_var2"] = ["Bye"] * 1000
+
+    X["date1"] = pd.date_range("2020-02-24", periods=1000, freq="T")
+    X["date2"] = pd.date_range("2021-09-29", periods=1000, freq="H")
+    X["date3"] = ["2020-02-24"] * 1000
+
+    print(X.head())
+
+Below we see the resulting dataframe:
+
+.. code:: python
+
+       num_var_1  num_var_2  num_var_3  num_var_4 cat_var1 cat_var2  \
+    0  -1.558594   1.634123   1.556932   2.869318    Hello      Bye
+    1   1.499925   1.651008   1.159977   2.510196    Hello      Bye
+    2   0.277127  -0.263527   0.532159   0.274491    Hello      Bye
+    3  -1.139190  -1.131193   2.296540   1.189781    Hello      Bye
+    4  -0.530061  -2.280109   2.469580   0.365617    Hello      Bye
+
+                    date1               date2       date3
+    0 2020-02-24 00:00:00 2021-09-29 00:00:00  2020-02-24
+    1 2020-02-24 00:01:00 2021-09-29 01:00:00  2020-02-24
+    2 2020-02-24 00:02:00 2021-09-29 02:00:00  2020-02-24
+    3 2020-02-24 00:03:00 2021-09-29 03:00:00  2020-02-24
+    4 2020-02-24 00:04:00 2021-09-29 04:00:00  2020-02-24
+
+We can now use :class:`find_categorical_and_numerical_variables()` to capture categorical
+and numerical variables in separate lists. So let's do that and then display the lists:
+
+.. code:: python
+
+    from feature_engine.variable_handling import find_categorical_and_numerical_variables
+
+    var_cat, var_num = find_categorical_and_numerical_variables(X)
+
+    var_cat, var_num
+
+Below we see the names of the categorical variables, followed by the names of the numerical
+variables:
+
+.. code:: python
+
+    (['cat_var1', 'cat_var2'],
+     ['num_var_1', 'num_var_2', 'num_var_3', 'num_var_4'])
+
+We can also use :class:`find_categorical_and_numerical_variables()` with a list of variables,
+to indentify their types:
+
+.. code:: python
+
+    var_cat, var_num = find_categorical_and_numerical_variables(X, ["num_var_1", "cat_var1"])
+
+    var_cat, var_num
+
+We see the resulting lists below:
+
+.. code:: python
+
+    (['cat_var1'], ['num_var_1'])
+
+If we pass a variable that is not of type numerical or categorical, :class:`find_categorical_and_numerical_variables()`
+will return an error:
+
+.. code:: python
+
+    find_categorical_and_numerical_variables(X, ["num_var_1", "cat_var1", "date1"])
+
+Below the error message:
+
+.. code:: python
+
+    TypeError: Some of the variables are neither numerical nor categorical.
\ No newline at end of file
diff --git a/docs/user_guide/variable_handling/find_or_check_categorical_variables.rst b/docs/user_guide/variable_handling/find_or_check_categorical_variables.rst
new file mode 100644
index 0000000..7fa9a5a
--- /dev/null
+++ b/docs/user_guide/variable_handling/find_or_check_categorical_variables.rst
@@ -0,0 +1,108 @@
+﻿.. _find_cat_vars:
+
+.. currentmodule:: feature_engine.variable_handling.variable_type_selection
+
+find_or_check_categorical_variables
+===================================
+
+With :class:`find_or_check_categorical_variables()` you can automatically capture in a list
+the names of all the variables of type object or categorical in the dataset.
+
+Let's create a toy dataset with numerical, categorical and datetime variables:
+
+.. code:: python
+
+    import pandas as pd
+    from sklearn.datasets import make_classification
+
+    X, y = make_classification(
+        n_samples=1000,
+        n_features=4,
+        n_redundant=1,
+        n_clusters_per_class=1,
+        weights=[0.50],
+        class_sep=2,
+        random_state=1,
+    )
+
+    # transform arrays into pandas df and series
+    colnames = [f"num_var_{i+1}" for i in range(4)]
+    X = pd.DataFrame(X, columns=colnames)
+
+    X["cat_var1"] = ["Hello"] * 1000
+    X["cat_var2"] = ["Bye"] * 1000
+
+    X["date1"] = pd.date_range("2020-02-24", periods=1000, freq="T")
+    X["date2"] = pd.date_range("2021-09-29", periods=1000, freq="H")
+    X["date3"] = ["2020-02-24"] * 1000
+
+    print(X.head())
+
+We see the resulting dataframe below:
+
+.. code:: python
+
+       num_var_1  num_var_2  num_var_3  num_var_4 cat_var1 cat_var2  \
+    0  -1.558594   1.634123   1.556932   2.869318    Hello      Bye
+    1   1.499925   1.651008   1.159977   2.510196    Hello      Bye
+    2   0.277127  -0.263527   0.532159   0.274491    Hello      Bye
+    3  -1.139190  -1.131193   2.296540   1.189781    Hello      Bye
+    4  -0.530061  -2.280109   2.469580   0.365617    Hello      Bye
+
+                    date1               date2       date3
+    0 2020-02-24 00:00:00 2021-09-29 00:00:00  2020-02-24
+    1 2020-02-24 00:01:00 2021-09-29 01:00:00  2020-02-24
+    2 2020-02-24 00:02:00 2021-09-29 02:00:00  2020-02-24
+    3 2020-02-24 00:03:00 2021-09-29 03:00:00  2020-02-24
+    4 2020-02-24 00:04:00 2021-09-29 04:00:00  2020-02-24
+
+We can now use :class:`find_or_check_categorical_variables()` to capture the names of all
+variables of type object or categorical in a list.
+
+So let's do that and then display the list:
+
+.. code:: python
+
+    from feature_engine.variable_handling import find_or_check_categorical_variables
+
+    var_cat = find_or_check_categorical_variables(X)
+
+    var_cat
+
+We see the variable names in the list below:
+
+.. code:: python
+
+    ['cat_var1', 'cat_var2']
+
+Note that when using the default parameters, :class:`find_or_check_categorical_variables()`
+will not return variables cast as object or categorical that could be parsed as datetime.
+Therefore, the variable `date3` was excluded from the returned list.
+
+We can force the function to select datetime variables cast as object as follows:
+
+.. code:: python
+
+    var_cat = find_or_check_categorical_variables(X, ["cat_var1", "date3"])
+
+    var_cat
+
+In this case, both variables, if object or categorical, will be in the resulting list:
+
+.. code:: python
+
+    ['cat_var1', 'date3']
+
+If we pass a variable that is not of type object or categorical, :class:`find_or_check_categorical_variables()`
+will return an error:
+
+.. code:: python
+
+    find_or_check_categorical_variables(X, ["cat_var1", "num_var_1"])
+
+Below we see the error message:
+
+.. code:: python
+
+    TypeError: Some of the variables are not categorical. Please cast them as categorical
+    or object before using this transformer.
\ No newline at end of file
diff --git a/docs/user_guide/variable_handling/find_or_check_datetime_variables.rst b/docs/user_guide/variable_handling/find_or_check_datetime_variables.rst
new file mode 100644
index 0000000..1d752e0
--- /dev/null
+++ b/docs/user_guide/variable_handling/find_or_check_datetime_variables.rst
@@ -0,0 +1,109 @@
+﻿.. _find_datetime_vars:
+
+.. currentmodule:: feature_engine.variable_handling.variable_type_selection
+
+find_or_check_datetime_variables
+================================
+
+With :class:`find_or_check_datetime_variables()` you can automatically capture in a list
+the names of all datetime variables in a dataset, whether they are parsed as datetime
+or object.
+
+Let's create a toy dataset with numerical, categorical and datetime variables:
+
+.. code:: python
+
+    import pandas as pd
+    from sklearn.datasets import make_classification
+
+    X, y = make_classification(
+        n_samples=1000,
+        n_features=4,
+        n_redundant=1,
+        n_clusters_per_class=1,
+        weights=[0.50],
+        class_sep=2,
+        random_state=1,
+    )
+
+    # transform arrays into pandas df and series
+    colnames = [f"num_var_{i+1}" for i in range(4)]
+    X = pd.DataFrame(X, columns=colnames)
+
+    X["cat_var1"] = ["Hello"] * 1000
+    X["cat_var2"] = ["Bye"] * 1000
+
+    X["date1"] = pd.date_range("2020-02-24", periods=1000, freq="T")
+    X["date2"] = pd.date_range("2021-09-29", periods=1000, freq="H")
+    X["date3"] = ["2020-02-24"] * 1000
+
+    print(X.head())
+
+We see the resulting dataframe below:
+
+.. code:: python
+
+       num_var_1  num_var_2  num_var_3  num_var_4 cat_var1 cat_var2  \
+    0  -1.558594   1.634123   1.556932   2.869318    Hello      Bye
+    1   1.499925   1.651008   1.159977   2.510196    Hello      Bye
+    2   0.277127  -0.263527   0.532159   0.274491    Hello      Bye
+    3  -1.139190  -1.131193   2.296540   1.189781    Hello      Bye
+    4  -0.530061  -2.280109   2.469580   0.365617    Hello      Bye
+
+                    date1               date2       date3
+    0 2020-02-24 00:00:00 2021-09-29 00:00:00  2020-02-24
+    1 2020-02-24 00:01:00 2021-09-29 01:00:00  2020-02-24
+    2 2020-02-24 00:02:00 2021-09-29 02:00:00  2020-02-24
+    3 2020-02-24 00:03:00 2021-09-29 03:00:00  2020-02-24
+    4 2020-02-24 00:04:00 2021-09-29 04:00:00  2020-02-24
+
+The dataframe has 3 datetime variables, two of them are of type datetime and one of type
+object.
+
+We can now use :class:`find_or_check_datetime_variables()` to capture all datetime variables
+regardless of their data type. So let's do that and then display the list:
+
+.. code:: python
+
+    from feature_engine.variable_handling import find_or_check_datetime_variables
+
+    var_date = find_or_check_datetime_variables(X)
+
+    var_date
+
+Below we see the variable names in the list:
+
+.. code:: python
+
+    ['date1', 'date2', 'date3']
+
+Note that :class:`find_or_check_datetime_variables()` captures all 3 datetime variables.
+The first 2 are of type datetime, whereas the third variable is of type object. But as it
+can be parsed as datetime, it will be captured in the list as well.
+
+We can also corroborate that a list of variables can be parsed as datetime as follows:
+
+.. code:: python
+
+    var_date = find_or_check_datetime_variables(X, ["date2", "date3"])
+
+    var_date
+
+In this case, both variables, if they can be parsed as datetime, will be in the resulting list:
+
+.. code:: python
+
+    ['date2', 'date3']
+
+If we pass a variable that can't be parsed as datetime, :class:`find_or_check_datetime_variables()`
+will return an error:
+
+.. code:: python
+
+    find_or_check_datetime_variables(X, ["date2", "cat_var1"])
+
+Below the error message:
+
+.. code:: python
+
+    TypeError: Some of the variables are not datetime.
\ No newline at end of file
diff --git a/docs/user_guide/variable_handling/find_or_check_numerical_variables.rst b/docs/user_guide/variable_handling/find_or_check_numerical_variables.rst
new file mode 100644
index 0000000..0ae350d
--- /dev/null
+++ b/docs/user_guide/variable_handling/find_or_check_numerical_variables.rst
@@ -0,0 +1,103 @@
+﻿.. _find_num_vars:
+
+.. currentmodule:: feature_engine.variable_handling.variable_type_selection
+
+find_or_check_numerical_variables
+=================================
+
+With :class:`find_or_check_numerical_variables()` you can automatically capture in a list
+the names of all the variables of type numerical in the dataset.
+
+Let's create a toy dataset with numerical, categorical and datetime variables:
+
+.. code:: python
+
+    import pandas as pd
+    from sklearn.datasets import make_classification
+
+    X, y = make_classification(
+        n_samples=1000,
+        n_features=4,
+        n_redundant=1,
+        n_clusters_per_class=1,
+        weights=[0.50],
+        class_sep=2,
+        random_state=1,
+    )
+
+    # transform arrays into pandas df and series
+    colnames = [f"num_var_{i+1}" for i in range(4)]
+    X = pd.DataFrame(X, columns=colnames)
+
+    X["cat_var1"] = ["Hello"] * 1000
+    X["cat_var2"] = ["Bye"] * 1000
+
+    X["date1"] = pd.date_range("2020-02-24", periods=1000, freq="T")
+    X["date2"] = pd.date_range("2021-09-29", periods=1000, freq="H")
+    X["date3"] = ["2020-02-24"] * 1000
+
+    print(X.head())
+
+We see the resulting dataframe below:
+
+.. code:: python
+
+       num_var_1  num_var_2  num_var_3  num_var_4 cat_var1 cat_var2  \
+    0  -1.558594   1.634123   1.556932   2.869318    Hello      Bye
+    1   1.499925   1.651008   1.159977   2.510196    Hello      Bye
+    2   0.277127  -0.263527   0.532159   0.274491    Hello      Bye
+    3  -1.139190  -1.131193   2.296540   1.189781    Hello      Bye
+    4  -0.530061  -2.280109   2.469580   0.365617    Hello      Bye
+
+                    date1               date2       date3
+    0 2020-02-24 00:00:00 2021-09-29 00:00:00  2020-02-24
+    1 2020-02-24 00:01:00 2021-09-29 01:00:00  2020-02-24
+    2 2020-02-24 00:02:00 2021-09-29 02:00:00  2020-02-24
+    3 2020-02-24 00:03:00 2021-09-29 03:00:00  2020-02-24
+    4 2020-02-24 00:04:00 2021-09-29 04:00:00  2020-02-24
+
+We can now use :class:`find_or_check_numerical_variables()` to capture the names of all
+numerical variables in a list. So let's do that and then display the list:
+
+.. code:: python
+
+    from feature_engine.variable_handling import find_or_check_numerical_variables
+
+    var_num = find_or_check_numerical_variables(X)
+
+    var_num
+
+We see the names of the variables in the list below:
+
+.. code:: python
+
+    ['num_var_1', 'num_var_2', 'num_var_3', 'num_var_4']
+
+We can also use :class:`find_or_check_numerical_variables()` with a list of variables. It
+will corroborate that the variables indicated in the list are of type numeric.
+
+.. code:: python
+
+    var_num = find_or_check_numerical_variables(X, ['num_var_1', 'num_var_2'])
+
+    var_num
+
+In this case, both variables, if numerical, will be in the resulting list:
+
+.. code:: python
+
+    ['num_var_1', 'num_var_2']
+
+If we pass a variable that is not of type numerical, :class:`find_or_check_numerical_variables()`
+will return an error:
+
+.. code:: python
+
+    find_or_check_numerical_variables(X, ['num_var_1', 'cat_var1'])
+
+Below we see the error message:
+
+.. code:: python
+
+    TypeError: Some of the variables are not numerical. Please cast them as numerical
+    before using this transformer.
\ No newline at end of file
diff --git a/docs/user_guide/variable_handling/index.rst b/docs/user_guide/variable_handling/index.rst
new file mode 100644
index 0000000..7b52d95
--- /dev/null
+++ b/docs/user_guide/variable_handling/index.rst
@@ -0,0 +1,26 @@
+.. -*- mode: rst -*-
+
+Variable handling functions
+===========================
+
+Feature-engine functions for finding variables of a specific type or ensuring that the
+variables are of the correct type.
+
+The functions take a dataframe as an argument and return the names of the variables in
+the desired type.
+
+You can also pass a dataframe with a list of variables to check if they are all of the
+desired type.
+
+These functions are used under the hood by all Feature-engine transformers to select the
+variables that they will modify or operate with.
+
+
+.. toctree::
+   :maxdepth: 1
+
+   find_all_variables
+   find_categorical_and_numerical_variables
+   find_or_check_categorical_variables
+   find_or_check_datetime_variables
+   find_or_check_numerical_variables
diff --git a/feature_engine/_base_transformers/base_numerical.py b/feature_engine/_base_transformers/base_numerical.py
index f5650ea..375957a 100644
--- a/feature_engine/_base_transformers/base_numerical.py
+++ b/feature_engine/_base_transformers/base_numerical.py
@@ -7,17 +7,17 @@ import pandas as pd
 from sklearn.base import BaseEstimator, TransformerMixin
 from sklearn.utils.validation import check_is_fitted
 
-from feature_engine._variable_handling.variable_type_selection import (
-    _find_or_check_numerical_variables,
-)
+from feature_engine._base_transformers.mixins import GetFeatureNamesOutMixin
 from feature_engine.dataframe_checks import (
     _check_contains_inf,
     _check_contains_na,
     _check_X_matches_training_df,
     check_X,
 )
-from feature_engine._base_transformers.mixins import GetFeatureNamesOutMixin
 from feature_engine.tags import _return_tags
+from feature_engine.variable_handling.variable_type_selection import (
+    find_or_check_numerical_variables,
+)
 
 
 class BaseNumericalTransformer(
@@ -58,7 +58,7 @@ class BaseNumericalTransformer(
         X = check_X(X)
 
         # find or check for numerical variables
-        self.variables_ = _find_or_check_numerical_variables(X, self.variables)
+        self.variables_ = find_or_check_numerical_variables(X, self.variables)
 
         # check if dataset contains na or inf
         _check_contains_na(X, self.variables_)
diff --git a/feature_engine/_base_transformers/mixins.py b/feature_engine/_base_transformers/mixins.py
index 90b3ef4..da79889 100644
--- a/feature_engine/_base_transformers/mixins.py
+++ b/feature_engine/_base_transformers/mixins.py
@@ -5,14 +5,14 @@ from numpy import ndarray
 from numpy.typing import ArrayLike
 from sklearn.utils.validation import check_is_fitted
 
-from feature_engine._variable_handling.variable_type_selection import (
-    _find_or_check_numerical_variables,
-)
 from feature_engine.dataframe_checks import (
     _check_contains_inf,
     _check_contains_na,
     check_X,
 )
+from feature_engine.variable_handling.variable_type_selection import (
+    find_or_check_numerical_variables,
+)
 
 
 class FitFromDictMixin:
@@ -47,7 +47,7 @@ class FitFromDictMixin:
 
         # find or check for numerical variables
         variables = [x for x in user_dict_.keys()]
-        self.variables_ = _find_or_check_numerical_variables(X, variables)
+        self.variables_ = find_or_check_numerical_variables(X, variables)
 
         # check if dataset contains na or inf
         _check_contains_na(X, self.variables_)
diff --git a/feature_engine/_check_input_parameters/check_init_input_params.py b/feature_engine/_check_input_parameters/check_init_input_params.py
index 2508e4b..f48c46e 100644
--- a/feature_engine/_check_input_parameters/check_init_input_params.py
+++ b/feature_engine/_check_input_parameters/check_init_input_params.py
@@ -1,4 +1,3 @@
-
 def _check_param_missing_values(missing_values):
     if missing_values not in ["raise", "ignore"]:
         raise ValueError(
diff --git a/feature_engine/_prediction/base_predictor.py b/feature_engine/_prediction/base_predictor.py
index b8af546..611fcdc 100644
--- a/feature_engine/_prediction/base_predictor.py
+++ b/feature_engine/_prediction/base_predictor.py
@@ -6,12 +6,6 @@ from sklearn.base import BaseEstimator
 from sklearn.pipeline import Pipeline
 from sklearn.utils.validation import check_is_fitted
 
-from feature_engine._variable_handling.init_parameter_checks import (
-    _check_init_parameter_variables,
-)
-from feature_engine._variable_handling.variable_type_selection import (
-    _find_categorical_and_numerical_variables,
-)
 from feature_engine.dataframe_checks import (
     _check_contains_inf,
     _check_contains_na,
@@ -25,6 +19,12 @@ from feature_engine.discretisation import (
 )
 from feature_engine.encoding import MeanEncoder
 from feature_engine.tags import _return_tags
+from feature_engine.variable_handling._init_parameter_checks import (
+    _check_init_parameter_variables,
+)
+from feature_engine.variable_handling.variable_type_selection import (
+    find_categorical_and_numerical_variables,
+)
 
 
 class BaseTargetMeanEstimator(BaseEstimator):
@@ -121,7 +121,7 @@ class BaseTargetMeanEstimator(BaseEstimator):
         (
             self.variables_categorical_,
             self.variables_numerical_,
-        ) = _find_categorical_and_numerical_variables(X, self.variables)
+        ) = find_categorical_and_numerical_variables(X, self.variables)
 
         # check for missing values
         _check_contains_na(X, self.variables_numerical_)
diff --git a/feature_engine/_variable_handling/__init__.py b/feature_engine/_variable_handling/__init__.py
deleted file mode 100644
index e69de29..0000000
diff --git a/feature_engine/creation/base_creation.py b/feature_engine/creation/base_creation.py
index e40a0a4..44d860d 100644
--- a/feature_engine/creation/base_creation.py
+++ b/feature_engine/creation/base_creation.py
@@ -9,9 +9,6 @@ from feature_engine._check_input_parameters.check_init_input_params import (
     _check_param_drop_original,
     _check_param_missing_values,
 )
-from feature_engine._variable_handling.variable_type_selection import (
-    _find_or_check_numerical_variables,
-)
 from feature_engine.dataframe_checks import (
     _check_contains_inf,
     _check_contains_na,
@@ -19,6 +16,9 @@ from feature_engine.dataframe_checks import (
     check_X,
 )
 from feature_engine.tags import _return_tags
+from feature_engine.variable_handling.variable_type_selection import (
+    find_or_check_numerical_variables,
+)
 
 
 class BaseCreation(BaseEstimator, TransformerMixin, GetFeatureNamesOutMixin):
@@ -53,12 +53,12 @@ class BaseCreation(BaseEstimator, TransformerMixin, GetFeatureNamesOutMixin):
         X = check_X(X)
 
         # check variables are numerical
-        self.variables_: List[Union[str, int]] = _find_or_check_numerical_variables(
+        self.variables_: List[Union[str, int]] = find_or_check_numerical_variables(
             X, self.variables
         )
 
         if hasattr(self, "reference"):
-            _find_or_check_numerical_variables(X, self.reference)
+            find_or_check_numerical_variables(X, self.reference)
 
         # check if dataset contains na
         if self.missing_values == "raise":
diff --git a/feature_engine/creation/cyclical_features.py b/feature_engine/creation/cyclical_features.py
index 1d6d7b4..c1edd95 100644
--- a/feature_engine/creation/cyclical_features.py
+++ b/feature_engine/creation/cyclical_features.py
@@ -28,7 +28,7 @@ from feature_engine._docstrings.methods import (
     _transform_creation_docstring,
 )
 from feature_engine._docstrings.substitute import Substitution
-from feature_engine._variable_handling.init_parameter_checks import (
+from feature_engine.variable_handling._init_parameter_checks import (
     _check_init_parameter_variables,
 )
 
diff --git a/feature_engine/dataframe_checks.py b/feature_engine/dataframe_checks.py
index dd9fc6a..95ae2e8 100644
--- a/feature_engine/dataframe_checks.py
+++ b/feature_engine/dataframe_checks.py
@@ -243,7 +243,8 @@ def _check_X_matches_training_df(X: pd.DataFrame, reference: int) -> None:
 
 
 def _check_contains_na(
-    X: pd.DataFrame, variables: List[Union[str, int]],
+    X: pd.DataFrame,
+    variables: List[Union[str, int]],
 ) -> None:
     """
     Checks if DataFrame contains null values in the selected columns.
diff --git a/feature_engine/datetime/datetime.py b/feature_engine/datetime/datetime.py
index b2a92e1..246d281 100644
--- a/feature_engine/datetime/datetime.py
+++ b/feature_engine/datetime/datetime.py
@@ -18,15 +18,6 @@ from feature_engine._docstrings.methods import (
     _fit_transform_docstring,
 )
 from feature_engine._docstrings.substitute import Substitution
-from feature_engine._variable_handling.init_parameter_checks import (
-    _check_init_parameter_variables,
-)
-from feature_engine._variable_handling.variable_type_checks import (
-    _is_categorical_and_is_datetime,
-)
-from feature_engine._variable_handling.variable_type_selection import (
-    _find_or_check_datetime_variables,
-)
 from feature_engine.dataframe_checks import (
     _check_contains_na,
     _check_X_matches_training_df,
@@ -38,6 +29,15 @@ from feature_engine.datetime._datetime_constants import (
     FEATURES_SUFFIXES,
     FEATURES_SUPPORTED,
 )
+from feature_engine.variable_handling._init_parameter_checks import (
+    _check_init_parameter_variables,
+)
+from feature_engine.variable_handling._variable_type_checks import (
+    _is_categorical_and_is_datetime,
+)
+from feature_engine.variable_handling.variable_type_selection import (
+    find_or_check_datetime_variables,
+)
 
 
 @Substitution(
@@ -255,7 +255,7 @@ class DatetimeFeatures(BaseEstimator, TransformerMixin, GetFeatureNamesOutMixin)
 
         else:
             # find or check for datetime variables
-            self.variables_ = _find_or_check_datetime_variables(X, self.variables)
+            self.variables_ = find_or_check_datetime_variables(X, self.variables)
 
             # check if datetime variables contains na
             if self.missing_values == "raise":
diff --git a/feature_engine/discretisation/decision_tree.py b/feature_engine/discretisation/decision_tree.py
index 10a8813..88a3e9e 100644
--- a/feature_engine/discretisation/decision_tree.py
+++ b/feature_engine/discretisation/decision_tree.py
@@ -19,10 +19,10 @@ from feature_engine._docstrings.init_parameters.all_trasnformers import (
 )
 from feature_engine._docstrings.methods import _fit_transform_docstring
 from feature_engine._docstrings.substitute import Substitution
-from feature_engine._variable_handling.init_parameter_checks import (
+from feature_engine.tags import _return_tags
+from feature_engine.variable_handling._init_parameter_checks import (
     _check_init_parameter_variables,
 )
-from feature_engine.tags import _return_tags
 
 
 @Substitution(
diff --git a/feature_engine/discretisation/equal_frequency.py b/feature_engine/discretisation/equal_frequency.py
index 1d81ac3..86d5230 100644
--- a/feature_engine/discretisation/equal_frequency.py
+++ b/feature_engine/discretisation/equal_frequency.py
@@ -25,10 +25,10 @@ from feature_engine._docstrings.methods import (
     _transform_discretiser_docstring,
 )
 from feature_engine._docstrings.substitute import Substitution
-from feature_engine._variable_handling.init_parameter_checks import (
+from feature_engine.discretisation.base_discretiser import BaseDiscretiser
+from feature_engine.variable_handling._init_parameter_checks import (
     _check_init_parameter_variables,
 )
-from feature_engine.discretisation.base_discretiser import BaseDiscretiser
 
 
 @Substitution(
diff --git a/feature_engine/discretisation/equal_width.py b/feature_engine/discretisation/equal_width.py
index 035569a..ebbf9e0 100644
--- a/feature_engine/discretisation/equal_width.py
+++ b/feature_engine/discretisation/equal_width.py
@@ -25,10 +25,10 @@ from feature_engine._docstrings.methods import (
     _transform_discretiser_docstring,
 )
 from feature_engine._docstrings.substitute import Substitution
-from feature_engine._variable_handling.init_parameter_checks import (
+from feature_engine.discretisation.base_discretiser import BaseDiscretiser
+from feature_engine.variable_handling._init_parameter_checks import (
     _check_init_parameter_variables,
 )
-from feature_engine.discretisation.base_discretiser import BaseDiscretiser
 
 
 @Substitution(
diff --git a/feature_engine/discretisation/geometric_width.py b/feature_engine/discretisation/geometric_width.py
index 8512fac..5947de8 100644
--- a/feature_engine/discretisation/geometric_width.py
+++ b/feature_engine/discretisation/geometric_width.py
@@ -23,7 +23,7 @@ from feature_engine._docstrings.methods import (
     _transform_discretiser_docstring,
 )
 from feature_engine._docstrings.substitute import Substitution
-from feature_engine._variable_handling.init_parameter_checks import (
+from feature_engine.variable_handling._init_parameter_checks import (
     _check_init_parameter_variables,
 )
 from feature_engine.discretisation.base_discretiser import BaseDiscretiser
diff --git a/feature_engine/encoding/base_encoder.py b/feature_engine/encoding/base_encoder.py
index 428a211..c642cc4 100644
--- a/feature_engine/encoding/base_encoder.py
+++ b/feature_engine/encoding/base_encoder.py
@@ -12,19 +12,19 @@ from feature_engine._docstrings.init_parameters.all_trasnformers import (
 )
 from feature_engine._docstrings.init_parameters.encoders import _ignore_format_docstring
 from feature_engine._docstrings.substitute import Substitution
-from feature_engine._variable_handling.init_parameter_checks import (
-    _check_init_parameter_variables,
-)
-from feature_engine._variable_handling.variable_type_selection import (
-    _find_all_variables,
-    _find_or_check_categorical_variables,
-)
 from feature_engine.dataframe_checks import (
     _check_optional_contains_na,
     _check_X_matches_training_df,
     check_X,
 )
 from feature_engine.tags import _return_tags
+from feature_engine.variable_handling._init_parameter_checks import (
+    _check_init_parameter_variables,
+)
+from feature_engine.variable_handling.variable_type_selection import (
+    find_all_variables,
+    find_or_check_categorical_variables,
+)
 
 
 @Substitution(
@@ -132,12 +132,12 @@ class CategoricalMethodsMixin(BaseEstimator, TransformerMixin, GetFeatureNamesOu
         """
         if self.ignore_format is False:
             # find categorical variables or check variables entered by user are object
-            variables_: List[Union[str, int]] = _find_or_check_categorical_variables(
+            variables_: List[Union[str, int]] = find_or_check_categorical_variables(
                 X, self.variables
             )
         else:
             # select all variables or check variables entered by the user
-            variables_ = _find_all_variables(X, self.variables)
+            variables_ = find_all_variables(X, self.variables)
 
         return variables_
 
diff --git a/feature_engine/imputation/arbitrary_number.py b/feature_engine/imputation/arbitrary_number.py
index 8e1767c..d2fea18 100644
--- a/feature_engine/imputation/arbitrary_number.py
+++ b/feature_engine/imputation/arbitrary_number.py
@@ -20,14 +20,14 @@ from feature_engine._docstrings.methods import (
     _transform_imputers_docstring,
 )
 from feature_engine._docstrings.substitute import Substitution
-from feature_engine._variable_handling.init_parameter_checks import (
+from feature_engine.dataframe_checks import check_X
+from feature_engine.imputation.base_imputer import BaseImputer
+from feature_engine.variable_handling._init_parameter_checks import (
     _check_init_parameter_variables,
 )
-from feature_engine._variable_handling.variable_type_selection import (
-    _find_or_check_numerical_variables,
+from feature_engine.variable_handling.variable_type_selection import (
+    find_or_check_numerical_variables,
 )
-from feature_engine.dataframe_checks import check_X
-from feature_engine.imputation.base_imputer import BaseImputer
 
 
 @Substitution(
@@ -148,12 +148,12 @@ class ArbitraryNumberImputer(BaseImputer):
         # find or check for numerical variables
         # create the imputer dictionary
         if self.imputer_dict:
-            self.variables_ = _find_or_check_numerical_variables(
+            self.variables_ = find_or_check_numerical_variables(
                 X, self.imputer_dict.keys()  # type: ignore
             )
             self.imputer_dict_ = self.imputer_dict
         else:
-            self.variables_ = _find_or_check_numerical_variables(X, self.variables)
+            self.variables_ = find_or_check_numerical_variables(X, self.variables)
             self.imputer_dict_ = {var: self.arbitrary_number for var in self.variables_}
 
         self._get_feature_names_in(X)
diff --git a/feature_engine/imputation/categorical.py b/feature_engine/imputation/categorical.py
index 8f77e33..16942f5 100644
--- a/feature_engine/imputation/categorical.py
+++ b/feature_engine/imputation/categorical.py
@@ -16,16 +16,16 @@ from feature_engine._docstrings.methods import (
     _transform_imputers_docstring,
 )
 from feature_engine._docstrings.substitute import Substitution
-from feature_engine._variable_handling.init_parameter_checks import (
-    _check_init_parameter_variables,
-)
-from feature_engine._variable_handling.variable_type_selection import (
-    _find_all_variables,
-    _find_or_check_categorical_variables,
-)
 from feature_engine.dataframe_checks import check_X
 from feature_engine.imputation.base_imputer import BaseImputer
 from feature_engine.tags import _return_tags
+from feature_engine.variable_handling._init_parameter_checks import (
+    _check_init_parameter_variables,
+)
+from feature_engine.variable_handling.variable_type_selection import (
+    find_all_variables,
+    find_or_check_categorical_variables,
+)
 
 
 @Substitution(
@@ -171,10 +171,10 @@ class CategoricalImputer(BaseImputer):
             # categorical
             self.variables_: List[
                 Union[str, int]
-            ] = _find_or_check_categorical_variables(X, self.variables)
+            ] = find_or_check_categorical_variables(X, self.variables)
         else:
             # select all variables or check variables entered by the user
-            self.variables_ = _find_all_variables(X, self.variables)
+            self.variables_ = find_all_variables(X, self.variables)
 
         if self.imputation_method == "missing":
             self.imputer_dict_ = {var: self.fill_value for var in self.variables_}
diff --git a/feature_engine/imputation/drop_missing_data.py b/feature_engine/imputation/drop_missing_data.py
index b13f2a8..cd9e6fe 100644
--- a/feature_engine/imputation/drop_missing_data.py
+++ b/feature_engine/imputation/drop_missing_data.py
@@ -11,15 +11,13 @@ from feature_engine._docstrings.fit_attributes import (
 )
 from feature_engine._docstrings.methods import _fit_transform_docstring
 from feature_engine._docstrings.substitute import Substitution
-from feature_engine._variable_handling.init_parameter_checks import (
-    _check_init_parameter_variables,
-)
-from feature_engine._variable_handling.variable_type_selection import (
-    _find_all_variables,
-)
 from feature_engine.dataframe_checks import check_X
 from feature_engine.imputation.base_imputer import BaseImputer
 from feature_engine.tags import _return_tags
+from feature_engine.variable_handling._init_parameter_checks import (
+    _check_init_parameter_variables,
+)
+from feature_engine.variable_handling.variable_type_selection import find_all_variables
 
 
 @Substitution(
@@ -146,7 +144,7 @@ class DropMissingData(BaseImputer):
         X = check_X(X)
 
         # find variables for which indicator should be added
-        self.variables_ = _find_all_variables(X, self.variables)
+        self.variables_ = find_all_variables(X, self.variables)
 
         # If user passes a threshold, then missing_only is ignored:
         if self.threshold is None and self.missing_only is True:
diff --git a/feature_engine/imputation/end_tail.py b/feature_engine/imputation/end_tail.py
index 5b316ad..a8fa927 100644
--- a/feature_engine/imputation/end_tail.py
+++ b/feature_engine/imputation/end_tail.py
@@ -19,14 +19,14 @@ from feature_engine._docstrings.methods import (
     _transform_imputers_docstring,
 )
 from feature_engine._docstrings.substitute import Substitution
-from feature_engine._variable_handling.init_parameter_checks import (
+from feature_engine.dataframe_checks import check_X
+from feature_engine.imputation.base_imputer import BaseImputer
+from feature_engine.variable_handling._init_parameter_checks import (
     _check_init_parameter_variables,
 )
-from feature_engine._variable_handling.variable_type_selection import (
-    _find_or_check_numerical_variables,
+from feature_engine.variable_handling.variable_type_selection import (
+    find_or_check_numerical_variables,
 )
-from feature_engine.dataframe_checks import check_X
-from feature_engine.imputation.base_imputer import BaseImputer
 
 
 @Substitution(
@@ -175,7 +175,7 @@ class EndTailImputer(BaseImputer):
         X = check_X(X)
 
         # find or check for numerical variables
-        self.variables_ = _find_or_check_numerical_variables(X, self.variables)
+        self.variables_ = find_or_check_numerical_variables(X, self.variables)
 
         # estimate imputation values
         if self.imputation_method == "max":
diff --git a/feature_engine/imputation/mean_median.py b/feature_engine/imputation/mean_median.py
index 38d7b8c..36d6cac 100644
--- a/feature_engine/imputation/mean_median.py
+++ b/feature_engine/imputation/mean_median.py
@@ -19,14 +19,14 @@ from feature_engine._docstrings.methods import (
     _transform_imputers_docstring,
 )
 from feature_engine._docstrings.substitute import Substitution
-from feature_engine._variable_handling.init_parameter_checks import (
+from feature_engine.dataframe_checks import check_X
+from feature_engine.imputation.base_imputer import BaseImputer
+from feature_engine.variable_handling._init_parameter_checks import (
     _check_init_parameter_variables,
 )
-from feature_engine._variable_handling.variable_type_selection import (
-    _find_or_check_numerical_variables,
+from feature_engine.variable_handling.variable_type_selection import (
+    find_or_check_numerical_variables,
 )
-from feature_engine.dataframe_checks import check_X
-from feature_engine.imputation.base_imputer import BaseImputer
 
 
 @Substitution(
@@ -125,7 +125,7 @@ class MeanMedianImputer(BaseImputer):
         X = check_X(X)
 
         # find or check for numerical variables
-        self.variables_ = _find_or_check_numerical_variables(X, self.variables)
+        self.variables_ = find_or_check_numerical_variables(X, self.variables)
 
         # find imputation parameters: mean or median
         if self.imputation_method == "mean":
diff --git a/feature_engine/imputation/missing_indicator.py b/feature_engine/imputation/missing_indicator.py
index ee09dd5..2cc0906 100644
--- a/feature_engine/imputation/missing_indicator.py
+++ b/feature_engine/imputation/missing_indicator.py
@@ -11,15 +11,13 @@ from feature_engine._docstrings.fit_attributes import (
 )
 from feature_engine._docstrings.methods import _fit_transform_docstring
 from feature_engine._docstrings.substitute import Substitution
-from feature_engine._variable_handling.init_parameter_checks import (
-    _check_init_parameter_variables,
-)
-from feature_engine._variable_handling.variable_type_selection import (
-    _find_all_variables,
-)
 from feature_engine.dataframe_checks import check_X
 from feature_engine.imputation.base_imputer import BaseImputer
 from feature_engine.tags import _return_tags
+from feature_engine.variable_handling._init_parameter_checks import (
+    _check_init_parameter_variables,
+)
+from feature_engine.variable_handling.variable_type_selection import find_all_variables
 
 
 @Substitution(
@@ -130,7 +128,7 @@ class AddMissingIndicator(BaseImputer):
         X = check_X(X)
 
         # find variables for which indicator should be added
-        self.variables_ = _find_all_variables(X, self.variables)
+        self.variables_ = find_all_variables(X, self.variables)
 
         if self.missing_only is True:
             self.variables_ = [
diff --git a/feature_engine/imputation/random_sample.py b/feature_engine/imputation/random_sample.py
index d1f7f43..40e3f6f 100644
--- a/feature_engine/imputation/random_sample.py
+++ b/feature_engine/imputation/random_sample.py
@@ -16,15 +16,13 @@ from feature_engine._docstrings.methods import (
     _transform_imputers_docstring,
 )
 from feature_engine._docstrings.substitute import Substitution
-from feature_engine._variable_handling.init_parameter_checks import (
-    _check_init_parameter_variables,
-)
-from feature_engine._variable_handling.variable_type_selection import (
-    _find_all_variables,
-)
 from feature_engine.dataframe_checks import check_X
 from feature_engine.imputation.base_imputer import BaseImputer
 from feature_engine.tags import _return_tags
+from feature_engine.variable_handling._init_parameter_checks import (
+    _check_init_parameter_variables,
+)
+from feature_engine.variable_handling.variable_type_selection import find_all_variables
 
 
 # for RandomSampleImputer
@@ -185,7 +183,7 @@ class RandomSampleImputer(BaseImputer):
         X = check_X(X)
 
         # find variables to impute
-        self.variables_ = _find_all_variables(X, self.variables)
+        self.variables_ = find_all_variables(X, self.variables)
 
         # take a copy of the selected variables
         self.X_ = X[self.variables_].copy()
diff --git a/feature_engine/outliers/artbitrary.py b/feature_engine/outliers/artbitrary.py
index 6fa7195..d010aec 100644
--- a/feature_engine/outliers/artbitrary.py
+++ b/feature_engine/outliers/artbitrary.py
@@ -24,9 +24,6 @@ from feature_engine._docstrings.methods import (
     _fit_transform_docstring,
 )
 from feature_engine._docstrings.substitute import Substitution
-from feature_engine._variable_handling.variable_type_selection import (
-    _find_or_check_numerical_variables,
-)
 from feature_engine.dataframe_checks import (
     _check_contains_inf,
     _check_contains_na,
@@ -34,6 +31,9 @@ from feature_engine.dataframe_checks import (
 )
 from feature_engine.outliers.base_outlier import BaseOutlier
 from feature_engine.tags import _return_tags
+from feature_engine.variable_handling.variable_type_selection import (
+    find_or_check_numerical_variables,
+)
 
 
 @Substitution(
@@ -145,7 +145,7 @@ class ArbitraryOutlierCapper(BaseOutlier):
             _check_contains_inf(X, self.variables_)
 
         # find or check for numerical variables
-        self.variables_ = _find_or_check_numerical_variables(X, self.variables_)
+        self.variables_ = find_or_check_numerical_variables(X, self.variables_)
 
         if self.max_capping_dict is not None:
             self.right_tail_caps_ = self.max_capping_dict
diff --git a/feature_engine/outliers/base_outlier.py b/feature_engine/outliers/base_outlier.py
index 4540828..6cbcf46 100644
--- a/feature_engine/outliers/base_outlier.py
+++ b/feature_engine/outliers/base_outlier.py
@@ -5,12 +5,6 @@ from sklearn.base import BaseEstimator, TransformerMixin
 from sklearn.utils.validation import check_is_fitted
 
 from feature_engine._base_transformers.mixins import GetFeatureNamesOutMixin
-from feature_engine._variable_handling.init_parameter_checks import (
-    _check_init_parameter_variables,
-)
-from feature_engine._variable_handling.variable_type_selection import (
-    _find_or_check_numerical_variables,
-)
 from feature_engine.dataframe_checks import (
     _check_contains_inf,
     _check_contains_na,
@@ -18,6 +12,12 @@ from feature_engine.dataframe_checks import (
     check_X,
 )
 from feature_engine.tags import _return_tags
+from feature_engine.variable_handling._init_parameter_checks import (
+    _check_init_parameter_variables,
+)
+from feature_engine.variable_handling.variable_type_selection import (
+    find_or_check_numerical_variables,
+)
 
 
 class BaseOutlier(BaseEstimator, TransformerMixin, GetFeatureNamesOutMixin):
@@ -196,7 +196,7 @@ class WinsorizerBase(BaseOutlier):
         X = check_X(X)
 
         # find or check for numerical variables
-        self.variables_ = _find_or_check_numerical_variables(X, self.variables)
+        self.variables_ = find_or_check_numerical_variables(X, self.variables)
 
         if self.missing_values == "raise":
             # check if dataset contains na
diff --git a/feature_engine/preprocessing/match_categories.py b/feature_engine/preprocessing/match_categories.py
index 3a811a1..f75709c 100644
--- a/feature_engine/preprocessing/match_categories.py
+++ b/feature_engine/preprocessing/match_categories.py
@@ -3,6 +3,7 @@ from typing import List, Optional, Union
 
 import pandas as pd
 
+from feature_engine._base_transformers.mixins import GetFeatureNamesOutMixin
 from feature_engine._docstrings.fit_attributes import (
     _feature_names_in_docstring,
     _n_features_in_docstring,
@@ -19,7 +20,6 @@ from feature_engine.encoding.base_encoder import (
     CategoricalInitMixinNA,
     CategoricalMethodsMixin,
 )
-from feature_engine._base_transformers.mixins import GetFeatureNamesOutMixin
 
 
 @Substitution(
diff --git a/feature_engine/preprocessing/match_columns.py b/feature_engine/preprocessing/match_columns.py
index 10db2fb..ff2b4f2 100644
--- a/feature_engine/preprocessing/match_columns.py
+++ b/feature_engine/preprocessing/match_columns.py
@@ -5,9 +5,9 @@ import pandas as pd
 from sklearn.base import BaseEstimator, TransformerMixin
 from sklearn.utils.validation import check_is_fitted
 
+from feature_engine._base_transformers.mixins import GetFeatureNamesOutMixin
 from feature_engine.dataframe_checks import _check_contains_na, check_X
 from feature_engine.tags import _return_tags
-from feature_engine._base_transformers.mixins import GetFeatureNamesOutMixin
 
 
 class MatchVariables(BaseEstimator, TransformerMixin, GetFeatureNamesOutMixin):
diff --git a/feature_engine/selection/base_recursive_selector.py b/feature_engine/selection/base_recursive_selector.py
index f7d0d29..fd7f188 100644
--- a/feature_engine/selection/base_recursive_selector.py
+++ b/feature_engine/selection/base_recursive_selector.py
@@ -3,15 +3,15 @@ from typing import List, Union
 import pandas as pd
 from sklearn.model_selection import cross_validate
 
-from feature_engine._variable_handling.init_parameter_checks import (
-    _check_init_parameter_variables,
-)
-from feature_engine._variable_handling.variable_type_selection import (
-    _find_or_check_numerical_variables,
-)
 from feature_engine.dataframe_checks import check_X_y
 from feature_engine.selection.base_selector import BaseSelector, get_feature_importances
 from feature_engine.tags import _return_tags
+from feature_engine.variable_handling._init_parameter_checks import (
+    _check_init_parameter_variables,
+)
+from feature_engine.variable_handling.variable_type_selection import (
+    find_or_check_numerical_variables,
+)
 
 Variables = Union[None, int, str, List[Union[str, int]]]
 
@@ -136,7 +136,7 @@ class BaseRecursiveSelector(BaseSelector):
         self._confirm_variables(X)
 
         # find numerical variables or check variables entered by user
-        self.variables_ = _find_or_check_numerical_variables(X, self.variables_)
+        self.variables_ = find_or_check_numerical_variables(X, self.variables_)
 
         # check that there are more than 1 variable to select from
         self._check_variable_number()
diff --git a/feature_engine/selection/base_selector.py b/feature_engine/selection/base_selector.py
index 7f9a094..7706971 100644
--- a/feature_engine/selection/base_selector.py
+++ b/feature_engine/selection/base_selector.py
@@ -4,11 +4,11 @@ from sklearn.base import BaseEstimator, TransformerMixin
 from sklearn.utils.validation import check_is_fitted
 
 from feature_engine._base_transformers.mixins import GetFeatureNamesOutMixin
-from feature_engine._variable_handling.variable_type_selection import (
-    _filter_out_variables_not_in_dataframe,
-)
 from feature_engine.dataframe_checks import _check_X_matches_training_df, check_X
 from feature_engine.tags import _return_tags
+from feature_engine.variable_handling.variable_type_selection import (
+    _filter_out_variables_not_in_dataframe,
+)
 
 
 def get_feature_importances(estimator):
diff --git a/feature_engine/selection/drop_constant_features.py b/feature_engine/selection/drop_constant_features.py
index e03df97..fff7a2f 100644
--- a/feature_engine/selection/drop_constant_features.py
+++ b/feature_engine/selection/drop_constant_features.py
@@ -11,12 +11,6 @@ from feature_engine._docstrings.init_parameters.selection import (
 )
 from feature_engine._docstrings.methods import _fit_transform_docstring
 from feature_engine._docstrings.substitute import Substitution
-from feature_engine._variable_handling.init_parameter_checks import (
-    _check_init_parameter_variables,
-)
-from feature_engine._variable_handling.variable_type_selection import (
-    _find_all_variables,
-)
 from feature_engine.dataframe_checks import _check_contains_na, check_X
 from feature_engine.selection._docstring import (
     _get_support_docstring,
@@ -25,6 +19,10 @@ from feature_engine.selection._docstring import (
 )
 from feature_engine.selection.base_selector import BaseSelector
 from feature_engine.tags import _return_tags
+from feature_engine.variable_handling._init_parameter_checks import (
+    _check_init_parameter_variables,
+)
+from feature_engine.variable_handling.variable_type_selection import find_all_variables
 
 Variables = Union[None, int, str, List[Union[str, int]]]
 
@@ -103,6 +101,35 @@ class DropConstantFeatures(BaseSelector):
     See Also
     --------
     sklearn.feature_selection.VarianceThreshold
+
+    Examples
+    --------
+
+    >>> import pandas as pd
+    >>> from feature_engine.selection import DropConstantFeatures
+    >>> X = pd.DataFrame(dict(x1 = [1,1,1,1],
+    >>>                     x2 = ["a", "a", "b", "c"],
+    >>>                     x3 = [True, False, False, True]))
+    >>> dcf = DropConstantFeatures()
+    >>> dcf.fit_transform(X)
+        x2     x3
+    0  a   True
+    1  a  False
+    2  b  False
+    3  c   True
+
+    Additionally, you can set the Threshold for quasi-constant features:
+
+    >>> X = pd.DataFrame(dict(x1 = [1,1,1,1],
+    >>>                      x2 = ["a", "a", "b", "c"],
+    >>>                      x3 = [True, False, False, False]))
+    >>> dcf = DropConstantFeatures(tol = 0.75)
+    >>> dcf.fit_transform(X)
+        x2
+    0  a
+    1  a
+    2  b
+    3  c
     """
 
     def __init__(
@@ -151,7 +178,7 @@ class DropConstantFeatures(BaseSelector):
         self._confirm_variables(X)
 
         # find all variables or check those entered are present in the dataframe
-        self.variables_ = _find_all_variables(X, self.variables_)
+        self.variables_ = find_all_variables(X, self.variables_)
 
         if self.missing_values == "raise":
             # check if dataset contains na
diff --git a/feature_engine/selection/drop_correlated_features.py b/feature_engine/selection/drop_correlated_features.py
index afc732c..eda9c28 100644
--- a/feature_engine/selection/drop_correlated_features.py
+++ b/feature_engine/selection/drop_correlated_features.py
@@ -11,12 +11,6 @@ from feature_engine._docstrings.init_parameters.selection import (
 )
 from feature_engine._docstrings.methods import _fit_transform_docstring
 from feature_engine._docstrings.substitute import Substitution
-from feature_engine._variable_handling.init_parameter_checks import (
-    _check_init_parameter_variables,
-)
-from feature_engine._variable_handling.variable_type_selection import (
-    _find_or_check_numerical_variables,
-)
 from feature_engine.dataframe_checks import (
     _check_contains_inf,
     _check_contains_na,
@@ -29,6 +23,12 @@ from feature_engine.selection._docstring import (
     _variables_numerical_docstring,
 )
 from feature_engine.selection.base_selector import BaseSelector
+from feature_engine.variable_handling._init_parameter_checks import (
+    _check_init_parameter_variables,
+)
+from feature_engine.variable_handling.variable_type_selection import (
+    find_or_check_numerical_variables,
+)
 
 Variables = Union[None, int, str, List[Union[str, int]]]
 
@@ -112,6 +112,20 @@ class DropCorrelatedFeatures(BaseSelector):
     --------
     pandas.corr
     feature_engine.selection.SmartCorrelationSelection
+
+    Examples
+    --------
+
+    >>> import pandas as pd
+    >>> from feature_engine.selection import DropCorrelatedFeatures
+    >>> X = pd.DataFrame(dict(x1 = [1,2,1,1], x2 = [2,4,3,1], x3 = [1, 0, 0, 1]))
+    >>> dcf = DropCorrelatedFeatures(threshold=0.7)
+    >>> dcf.fit_transform(X)
+        x1  x3
+    0   1   1
+    1   2   0
+    2   1   0
+    3   1   1
     """
 
     def __init__(
@@ -156,7 +170,7 @@ class DropCorrelatedFeatures(BaseSelector):
         self._confirm_variables(X)
 
         # find all numerical variables or check those entered are in the dataframe
-        self.variables_ = _find_or_check_numerical_variables(X, self.variables_)
+        self.variables_ = find_or_check_numerical_variables(X, self.variables_)
 
         # check that there are more than 1 variable to select from
         self._check_variable_number()
diff --git a/feature_engine/selection/drop_duplicate_features.py b/feature_engine/selection/drop_duplicate_features.py
index e4c72dc..fc5c5c3 100644
--- a/feature_engine/selection/drop_duplicate_features.py
+++ b/feature_engine/selection/drop_duplicate_features.py
@@ -1,3 +1,4 @@
+from collections import defaultdict
 from typing import List, Union
 
 import pandas as pd
@@ -11,12 +12,6 @@ from feature_engine._docstrings.init_parameters.selection import (
 )
 from feature_engine._docstrings.methods import _fit_transform_docstring
 from feature_engine._docstrings.substitute import Substitution
-from feature_engine._variable_handling.init_parameter_checks import (
-    _check_init_parameter_variables,
-)
-from feature_engine._variable_handling.variable_type_selection import (
-    _find_all_variables,
-)
 from feature_engine.dataframe_checks import _check_contains_na, check_X
 from feature_engine.selection._docstring import (
     _get_support_docstring,
@@ -26,6 +21,10 @@ from feature_engine.selection._docstring import (
 )
 from feature_engine.selection.base_selector import BaseSelector
 from feature_engine.tags import _return_tags
+from feature_engine.variable_handling._init_parameter_checks import (
+    _check_init_parameter_variables,
+)
+from feature_engine.variable_handling.variable_type_selection import find_all_variables
 
 Variables = Union[None, int, str, List[Union[str, int]]]
 
@@ -91,6 +90,21 @@ class DropDuplicateFeatures(BaseSelector):
     transform:
         Remove duplicated features.
 
+    Examples
+    --------
+
+    >>> import pandas as pd
+    >>> from feature_engine.selection import DropDuplicateFeatures
+    >>> X = pd.DataFrame(dict(x1 = [1,1,1,1],
+    >>>                     x2 = [1,1,1,1],
+    >>>                     x3 = [True, False, False, False]))
+    >>> ddf = DropDuplicateFeatures()
+    >>> ddf.fit_transform(X)
+        x1     x3
+    0   1   True
+    1   1  False
+    2   1  False
+    3   1  False
     """
 
     def __init__(
@@ -99,7 +113,6 @@ class DropDuplicateFeatures(BaseSelector):
         missing_values: str = "ignore",
         confirm_variables: bool = False,
     ):
-
         if missing_values not in ["raise", "ignore"]:
             raise ValueError("missing_values takes only values 'raise' or 'ignore'.")
 
@@ -127,7 +140,7 @@ class DropDuplicateFeatures(BaseSelector):
         self._confirm_variables(X)
 
         # find all variables or check those entered are in the dataframe
-        self.variables_ = _find_all_variables(X, self.variables_)
+        self.variables_ = find_all_variables(X, self.variables_)
 
         # check that there are more than 1 variable to select from
         self._check_variable_number()
@@ -136,42 +149,30 @@ class DropDuplicateFeatures(BaseSelector):
             # check if dataset contains na
             _check_contains_na(X, self.variables_)
 
-        # create tuples of duplicated feature groups
-        self.duplicated_feature_sets_ = []
-
-        # set to collect features that are duplicated
-        self.features_to_drop_ = set()  # type: ignore
-
-        # create set of examined features
-        _examined_features = set()
-
-        for feature in self.variables_:
-
-            # append so we can remove when we create the combinations
-            _examined_features.add(feature)
+        # collect duplicate features
+        _features_hashmap = defaultdict(list)
 
-            if feature not in self.features_to_drop_:
+        # hash the features
+        _X_hash = pd.util.hash_pandas_object(X[self.variables_].T, index=False)
 
-                _temp_set = set([feature])
+        # group the features by hash
+        for feature, feature_hash in _X_hash.items():
+            _features_hashmap[feature_hash].append(feature)
 
-                # features that have not been examined, are not currently examined and
-                # were not found duplicates
-                _features_to_compare = [
-                    f
-                    for f in self.variables_
-                    if f not in _examined_features.union(self.features_to_drop_)
-                ]
-
-                # create combinations:
-                for f2 in _features_to_compare:
-
-                    if X[feature].equals(X[f2]):
-                        self.features_to_drop_.add(f2)
-                        _temp_set.add(f2)
+        # create tuples of duplicated feature groups
+        self.duplicated_feature_sets_ = [
+            set(duplicate)
+            for duplicate in _features_hashmap.values()
+            if len(duplicate) > 1
+        ]
 
-                # if there are duplicated features
-                if len(_temp_set) > 1:
-                    self.duplicated_feature_sets_.append(_temp_set)
+        # set to collect features that are duplicated
+        self.features_to_drop_ = {
+            item
+            for duplicates in _features_hashmap.values()
+            for item in duplicates[1:]
+            if duplicates and len(duplicates) > 1
+        }
 
         # save input features
         self._get_feature_names_in(X)
diff --git a/feature_engine/selection/drop_features.py b/feature_engine/selection/drop_features.py
index 708bedd..ac01479 100644
--- a/feature_engine/selection/drop_features.py
+++ b/feature_engine/selection/drop_features.py
@@ -2,12 +2,10 @@ from typing import List, Union
 
 import pandas as pd
 
-from feature_engine._variable_handling.variable_type_selection import (
-    _find_all_variables,
-)
 from feature_engine.dataframe_checks import check_X
 from feature_engine.selection.base_selector import BaseSelector
 from feature_engine.tags import _return_tags
+from feature_engine.variable_handling.variable_type_selection import find_all_variables
 
 
 class DropFeatures(BaseSelector):
@@ -54,6 +52,22 @@ class DropFeatures(BaseSelector):
 
     transform:
         Drops indicated features.
+
+    Examples
+    --------
+
+    >>> import pandas as pd
+    >>> from feature_engine.selection import DropFeatures
+    >>> X = pd.DataFrame(dict(x1 = [1,2,3,4],
+    >>>                         x2 = ["a", "a", "b", "c"],
+    >>>                         x3 = [True, False, False, True]))
+    >>> df = DropFeatures(features_to_drop=["x2"])
+    >>> df.fit_transform(X)
+        x1     x3
+    0   1   True
+    1   2  False
+    2   3  False
+    3   4   True
     """
 
     def __init__(self, features_to_drop: List[Union[str, int]]):
@@ -83,7 +97,7 @@ class DropFeatures(BaseSelector):
         # present in the df.
         X[self.features_to_drop]
 
-        self.features_to_drop_ = _find_all_variables(X, variables=self.features_to_drop)
+        self.features_to_drop_ = find_all_variables(X, variables=self.features_to_drop)
 
         # check user is not removing all columns in the dataframe
         if len(self.features_to_drop_) == len(X.columns):
diff --git a/feature_engine/selection/drop_psi_features.py b/feature_engine/selection/drop_psi_features.py
index 80a621a..2de3803 100644
--- a/feature_engine/selection/drop_psi_features.py
+++ b/feature_engine/selection/drop_psi_features.py
@@ -15,12 +15,6 @@ from feature_engine._docstrings.init_parameters.selection import (
 )
 from feature_engine._docstrings.methods import _fit_transform_docstring
 from feature_engine._docstrings.substitute import Substitution
-from feature_engine._variable_handling.init_parameter_checks import (
-    _check_init_parameter_variables,
-)
-from feature_engine._variable_handling.variable_type_selection import (
-    _find_or_check_numerical_variables,
-)
 from feature_engine.dataframe_checks import (
     _check_contains_inf,
     _check_contains_na,
@@ -36,6 +30,12 @@ from feature_engine.selection._docstring import (
     _variables_numerical_docstring,
 )
 from feature_engine.selection.base_selector import BaseSelector
+from feature_engine.variable_handling._init_parameter_checks import (
+    _check_init_parameter_variables,
+)
+from feature_engine.variable_handling.variable_type_selection import (
+    find_or_check_numerical_variables,
+)
 
 Variables = Union[None, int, str, List[Union[str, int]]]
 
@@ -213,6 +213,28 @@ class DropHighPSIFeatures(BaseSelector):
     .. [1] Yurdakul B. "Statistical properties of population stability index".
        Western Michigan University, 2018.
        https://scholarworks.wmich.edu/dissertations/3208/
+
+    Examples
+    --------
+
+    >>> import pandas as pd
+    >>> from feature_engine.selection import DropHighPSIFeatures
+    >>> X = pd.DataFrame(dict(x1 = [1,1,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
+    >>>                 x2 = [32,87,6,32,11,44,8,7,9,0,32,87,6,32,11,44,8,7,9,0]))
+    >>> psi = DropHighPSIFeatures()
+    >>> psi.fit_transform(X)
+        x2
+    0   32
+    1   87
+    2    6
+    3   32
+    4   11
+    5   44
+    6    8
+    7    7
+    8    9
+    9    0
+    10  32
     """
 
     def __init__(
@@ -333,7 +355,7 @@ class DropHighPSIFeatures(BaseSelector):
         self._confirm_variables(X)
 
         # find numerical variables or check those entered are present in the dataframe
-        self.variables_ = _find_or_check_numerical_variables(X, self.variables_)
+        self.variables_ = find_or_check_numerical_variables(X, self.variables_)
 
         # Remove the split_col from the variables list. It might be added if the
         # variables are not defined at initialization.
diff --git a/feature_engine/selection/information_value.py b/feature_engine/selection/information_value.py
index 6140de9..3921463 100644
--- a/feature_engine/selection/information_value.py
+++ b/feature_engine/selection/information_value.py
@@ -14,13 +14,6 @@ from feature_engine._docstrings.init_parameters.selection import (
 )
 from feature_engine._docstrings.methods import _fit_transform_docstring
 from feature_engine._docstrings.substitute import Substitution
-from feature_engine._variable_handling.init_parameter_checks import (
-    _check_init_parameter_variables,
-)
-from feature_engine._variable_handling.variable_type_selection import (
-    _find_all_variables,
-    _find_categorical_and_numerical_variables,
-)
 from feature_engine.dataframe_checks import _check_contains_inf, _check_contains_na
 from feature_engine.discretisation import (
     EqualFrequencyDiscretiser,
@@ -34,6 +27,13 @@ from feature_engine.selection._docstring import (
 )
 from feature_engine.selection.base_selector import BaseSelector
 from feature_engine.tags import _return_tags
+from feature_engine.variable_handling._init_parameter_checks import (
+    _check_init_parameter_variables,
+)
+from feature_engine.variable_handling.variable_type_selection import (
+    find_all_variables,
+    find_categorical_and_numerical_variables,
+)
 
 Variables = Union[None, int, str, List[Union[str, int]]]
 
@@ -141,6 +141,25 @@ class SelectByInformationValue(BaseSelector, WoE):
 
     .. [2] WoE and IV for continuous variables
         https://www.listendata.com/2019/08/WOE-IV-Continuous-Dependent.html
+
+    Examples
+    --------
+
+    >>> import pandas as pd
+    >>> from feature_engine.selection import SelectByInformationValue
+    >>> X = pd.DataFrame(dict(x1 = [1,1,1,1,1,1],
+    >>>                     x2 = [3,2,2,3,3,2],
+    >>>                     x3 = ["a","b","c","a","c","b"]))
+    >>> y = pd.Series([1,1,1,0,0,0])
+    >>> iv = SelectByInformationValue()
+    >>> iv.fit_transform(X, y)
+        x2
+    0   3
+    1   2
+    2   2
+    3   3
+    4   3
+    5   2
     """
 
     def __init__(
@@ -193,9 +212,9 @@ class SelectByInformationValue(BaseSelector, WoE):
 
         # find categorical and numerical variables
         # find all variables or check those entered are present in the dataframe
-        self.variables_ = _find_all_variables(X, self.variables_, exclude_datetime=True)
+        self.variables_ = find_all_variables(X, self.variables_, exclude_datetime=True)
 
-        _, variables_numerical = _find_categorical_and_numerical_variables(
+        _, variables_numerical = find_categorical_and_numerical_variables(
             X, self.variables_
         )
 
diff --git a/feature_engine/selection/recursive_feature_addition.py b/feature_engine/selection/recursive_feature_addition.py
index fbc8230..cca2705 100644
--- a/feature_engine/selection/recursive_feature_addition.py
+++ b/feature_engine/selection/recursive_feature_addition.py
@@ -112,6 +112,27 @@ class RecursiveFeatureAddition(BaseRecursiveSelector):
 
     {transform}
 
+    Examples
+    --------
+
+    >>> import pandas as pd
+    >>> from sklearn.ensemble import RandomForestClassifier
+    >>> from feature_engine.selection import RecursiveFeatureAddition
+    >>> X = pd.DataFrame(dict(x1 = [1000,2000,1000,1000,2000,3000],
+    >>>                     x2 = [2,4,3,1,2,2],
+    >>>                     x3 = [1,1,1,0,0,0],
+    >>>                     x4 = [1,2,1,1,0,1],
+    >>>                     x5 = [1,1,1,1,1,1]))
+    >>> y = pd.Series([1,0,0,1,1,0])
+    >>> rfa = RecursiveFeatureAddition(RandomForestClassifier(random_state=42), cv=2)
+    >>> rfa.fit_transform(X, y)
+       x2  x4
+    0   2   1
+    1   4   2
+    2   3   1
+    3   1   1
+    4   2   0
+    5   2   1
     """
 
     def fit(self, X: pd.DataFrame, y: pd.Series):
diff --git a/feature_engine/selection/recursive_feature_elimination.py b/feature_engine/selection/recursive_feature_elimination.py
index 7c1a127..04f34a9 100644
--- a/feature_engine/selection/recursive_feature_elimination.py
+++ b/feature_engine/selection/recursive_feature_elimination.py
@@ -112,6 +112,27 @@ class RecursiveFeatureElimination(BaseRecursiveSelector):
 
     {transform}
 
+    Examples
+    --------
+
+    >>> import pandas as pd
+    >>> from sklearn.ensemble import RandomForestClassifier
+    >>> from feature_engine.selection import RecursiveFeatureElimination
+    >>> X = pd.DataFrame(dict(x1 = [1000,2000,1000,1000,2000,3000],
+    >>>                     x2 = [2,4,3,1,2,2],
+    >>>                     x3 = [1,1,1,0,0,0],
+    >>>                     x4 = [1,2,1,1,0,1],
+    >>>                     x5 = [1,1,1,1,1,1]))
+    >>> y = pd.Series([1,0,0,1,1,0])
+    >>> rfe = RecursiveFeatureElimination(RandomForestClassifier(random_state=2), cv=2)
+    >>> rfe.fit_transform(X, y)
+       x2
+    0   2
+    1   4
+    2   3
+    3   1
+    4   2
+    5   2
     """
 
     def fit(self, X: pd.DataFrame, y: pd.Series):
diff --git a/feature_engine/selection/shuffle_features.py b/feature_engine/selection/shuffle_features.py
index c4472ce..1dcee62 100644
--- a/feature_engine/selection/shuffle_features.py
+++ b/feature_engine/selection/shuffle_features.py
@@ -16,12 +16,6 @@ from feature_engine._docstrings.init_parameters.selection import (
 )
 from feature_engine._docstrings.methods import _fit_transform_docstring
 from feature_engine._docstrings.substitute import Substitution
-from feature_engine._variable_handling.init_parameter_checks import (
-    _check_init_parameter_variables,
-)
-from feature_engine._variable_handling.variable_type_selection import (
-    _find_or_check_numerical_variables,
-)
 from feature_engine.dataframe_checks import check_X_y
 from feature_engine.selection._docstring import (
     _cv_docstring,
@@ -38,6 +32,12 @@ from feature_engine.selection._docstring import (
 )
 from feature_engine.selection.base_selector import BaseSelector
 from feature_engine.tags import _return_tags
+from feature_engine.variable_handling._init_parameter_checks import (
+    _check_init_parameter_variables,
+)
+from feature_engine.variable_handling.variable_type_selection import (
+    find_or_check_numerical_variables,
+)
 
 Variables = Union[None, int, str, List[Union[str, int]]]
 
@@ -134,6 +134,32 @@ class SelectByShuffling(BaseSelector):
     See Also
     --------
     sklearn.inspection.permutation_importance
+
+    Examples
+    --------
+
+    >>> import pandas as pd
+    >>> from sklearn.ensemble import RandomForestClassifier
+    >>> from feature_engine.selection import SelectByShuffling
+    >>> X = pd.DataFrame(dict(x1 = [1000,2000,1000,1000,2000,3000],
+    >>>                     x2 = [2,4,3,1,2,2],
+    >>>                     x3 = [1,1,1,0,0,0],
+    >>>                     x4 = [1,2,1,1,0,1],
+    >>>                     x5 = [1,1,1,1,1,1]))
+    >>> y = pd.Series([1,0,0,1,1,0])
+    >>> sbs = SelectByShuffling(
+    >>>         RandomForestClassifier(random_state=42),
+    >>>         cv=2,
+    >>>         random_state=42,
+    >>>       )
+    >>> sbs.fit_transform(X, y)
+       x2  x4  x5
+    0   2   1   1
+    1   4   2   1
+    2   3   1   1
+    3   1   1   1
+    4   2   0   1
+    5   2   1   1
     """
 
     def __init__(
@@ -181,7 +207,7 @@ class SelectByShuffling(BaseSelector):
         self._confirm_variables(X)
 
         # find numerical variables or check variables entered by user
-        self.variables_ = _find_or_check_numerical_variables(X, self.variables_)
+        self.variables_ = find_or_check_numerical_variables(X, self.variables_)
 
         # check that there are more than 1 variable to select from
         self._check_variable_number()
diff --git a/feature_engine/selection/single_feature_performance.py b/feature_engine/selection/single_feature_performance.py
index 9d4d4a6..b9c0b67 100644
--- a/feature_engine/selection/single_feature_performance.py
+++ b/feature_engine/selection/single_feature_performance.py
@@ -13,12 +13,6 @@ from feature_engine._docstrings.init_parameters.selection import (
 )
 from feature_engine._docstrings.methods import _fit_transform_docstring
 from feature_engine._docstrings.substitute import Substitution
-from feature_engine._variable_handling.init_parameter_checks import (
-    _check_init_parameter_variables,
-)
-from feature_engine._variable_handling.variable_type_selection import (
-    _find_or_check_numerical_variables,
-)
 from feature_engine.dataframe_checks import check_X_y
 from feature_engine.selection._docstring import (
     _cv_docstring,
@@ -35,6 +29,12 @@ from feature_engine.selection._docstring import (
 )
 from feature_engine.selection.base_selector import BaseSelector
 from feature_engine.tags import _return_tags
+from feature_engine.variable_handling._init_parameter_checks import (
+    _check_init_parameter_variables,
+)
+from feature_engine.variable_handling.variable_type_selection import (
+    find_or_check_numerical_variables,
+)
 
 Variables = Union[None, int, str, List[Union[str, int]]]
 
@@ -115,6 +115,30 @@ class SelectBySingleFeaturePerformance(BaseSelector):
 
     .. [1] Galli S. "Machine Learning in Financial Risk Assessment".
         https://www.youtube.com/watch?v=KHGGlozsRtA
+
+    Examples
+    --------
+
+    >>> import pandas as pd
+    >>> from sklearn.ensemble import RandomForestClassifier
+    >>> from feature_engine.selection import SelectBySingleFeaturePerformance
+    >>> X = pd.DataFrame(dict(x1 = [1000,2000,1000,1000,2000,3000],
+    >>>                     x2 = [2,4,3,1,2,2],
+    >>>                     x3 = [1,1,1,0,0,0],
+    >>>                     x4 = [1,2,1,1,0,1],
+    >>>                     x5 = [1,1,1,1,1,1]))
+    >>> y = pd.Series([1,0,0,1,1,0])
+    >>> sfp = SelectBySingleFeaturePerformance(
+    >>>                     RandomForestClassifier(random_state=42),
+    >>>                     cv=2)
+    >>> sfp.fit_transform(X, y)
+        x2  x3
+    0   2   1
+    1   4   1
+    2   3   1
+    3   1   0
+    4   2   0
+    5   2   0
     """
 
     def __init__(
@@ -171,7 +195,7 @@ class SelectBySingleFeaturePerformance(BaseSelector):
         self._confirm_variables(X)
 
         # find numerical variables or check variables entered by user
-        self.variables_ = _find_or_check_numerical_variables(X, self.variables_)
+        self.variables_ = find_or_check_numerical_variables(X, self.variables_)
 
         if len(self.variables_) == 1 and self.threshold is None:
             raise ValueError(
diff --git a/feature_engine/selection/smart_correlation_selection.py b/feature_engine/selection/smart_correlation_selection.py
index fa39ce5..3d733dd 100644
--- a/feature_engine/selection/smart_correlation_selection.py
+++ b/feature_engine/selection/smart_correlation_selection.py
@@ -12,12 +12,6 @@ from feature_engine._docstrings.init_parameters.selection import (
 )
 from feature_engine._docstrings.methods import _fit_transform_docstring
 from feature_engine._docstrings.substitute import Substitution
-from feature_engine._variable_handling.init_parameter_checks import (
-    _check_init_parameter_variables,
-)
-from feature_engine._variable_handling.variable_type_selection import (
-    _find_or_check_numerical_variables,
-)
 from feature_engine.dataframe_checks import (
     _check_contains_inf,
     _check_contains_na,
@@ -33,6 +27,12 @@ from feature_engine.selection._docstring import (
     _variables_numerical_docstring,
 )
 from feature_engine.selection.base_selector import BaseSelector
+from feature_engine.variable_handling._init_parameter_checks import (
+    _check_init_parameter_variables,
+)
+from feature_engine.variable_handling.variable_type_selection import (
+    find_or_check_numerical_variables,
+)
 
 Variables = Union[None, int, str, List[Union[str, int]]]
 
@@ -152,6 +152,36 @@ class SmartCorrelatedSelection(BaseSelector):
     --------
     pandas.corr
     feature_engine.selection.DropCorrelatedFeatures
+
+    Examples
+    --------
+
+    >>> import pandas as pd
+    >>> from feature_engine.selection import SmartCorrelatedSelection
+    >>> X = pd.DataFrame(dict(x1 = [1,2,1,1],
+    >>>                 x2 = [2,4,3,1],
+    >>>                 x3 = [1, 0, 0, 0]))
+    >>> scs = SmartCorrelatedSelection(threshold=0.7)
+    >>> scs.fit_transform(X)
+       x2  x3
+    0   2   1
+    1   4   0
+    2   3   0
+    3   1   0
+
+    It is also possible alternative selection methods, in this case seleting
+    features with higher variance:
+
+    >>> X = pd.DataFrame(dict(x1 = [2,4,3,1],
+    >>>                 x2 = [1000,2000,1500,500],
+    >>>                 x3 = [1, 0, 0, 0]))
+    >>> scs = SmartCorrelatedSelection(threshold=0.7, selection_method="variance")
+    >>> scs.fit_transform(X)
+         x2  x3
+    0  1000   1
+    1  2000   0
+    2  1500   0
+    3   500   0
     """
 
     def __init__(
@@ -229,7 +259,7 @@ class SmartCorrelatedSelection(BaseSelector):
         self._confirm_variables(X)
 
         # find all numerical variables or check those entered are in the dataframe
-        self.variables_ = _find_or_check_numerical_variables(X, self.variables_)
+        self.variables_ = find_or_check_numerical_variables(X, self.variables_)
 
         # check that there are more than 1 variable to select from
         self._check_variable_number()
diff --git a/feature_engine/selection/target_mean_selection.py b/feature_engine/selection/target_mean_selection.py
index 2281468..86078ce 100644
--- a/feature_engine/selection/target_mean_selection.py
+++ b/feature_engine/selection/target_mean_selection.py
@@ -15,12 +15,6 @@ from feature_engine._docstrings.methods import _fit_transform_docstring
 from feature_engine._docstrings.substitute import Substitution
 from feature_engine._prediction.target_mean_classifier import TargetMeanClassifier
 from feature_engine._prediction.target_mean_regressor import TargetMeanRegressor
-from feature_engine._variable_handling.init_parameter_checks import (
-    _check_init_parameter_variables,
-)
-from feature_engine._variable_handling.variable_type_selection import (
-    _find_all_variables,
-)
 from feature_engine.dataframe_checks import check_X_y
 from feature_engine.selection._docstring import (
     _cv_docstring,
@@ -38,6 +32,10 @@ from feature_engine.selection._selection_constants import (
 )
 from feature_engine.selection.base_selector import BaseSelector
 from feature_engine.tags import _return_tags
+from feature_engine.variable_handling._init_parameter_checks import (
+    _check_init_parameter_variables,
+)
+from feature_engine.variable_handling.variable_type_selection import find_all_variables
 
 Variables = Union[None, int, str, List[Union[str, int]]]
 
@@ -169,6 +167,41 @@ class SelectByTargetMeanPerformance(BaseSelector):
     .. [1] Miller, et al. "Predicting customer behaviour: The University of Melbourne’s
         KDD Cup report". JMLR Workshop and Conference Proceeding. KDD 2009
         http://proceedings.mlr.press/v7/miller09/miller09.pdf
+
+    Examples
+    --------
+
+    >>> from sklearn.ensemble import RandomForestClassifier
+    >>> from feature_engine.selection import SelectByTargetMeanPerformance
+    >>> X = pd.DataFrame(dict(x1 = [1000,2000,1000,1000,2000,3000],
+    >>>                     x2 = [1,1,1,0,0,0],
+    >>>                     x3 = [1,2,1,1,0,1],
+    >>>                     x4 = [1,1,1,1,1,1]))
+    >>> y = pd.Series([1,0,0,1,1,0])
+    >>> tmp = SelectByTargetMeanPerformance(bins = 3, cv=2,scoring='accuracy')
+    >>> tmp.fit_transform(X, y)
+        x2  x3  x4
+    0   1   1   1
+    1   1   2   1
+    2   1   1   1
+    3   0   1   1
+    4   0   0   1
+    5   0   1   1
+
+    This transformer also works with Categorical examples:
+
+    >>> X = pd.DataFrame(dict(x1 = ["a","b","a","a","b","b"],
+    >>>             x2 = ["a","a","a","b","b","b"]))
+    >>> y = pd.Series([1,0,0,1,1,0])
+    >>> tmp = SelectByTargetMeanPerformance(bins = 3, cv=2,scoring='accuracy')
+    >>> tmp.fit_transform(X, y)
+      x2
+    0  a
+    1  a
+    2  a
+    3  b
+    4  b
+    5  b
     """
 
     def __init__(
@@ -239,7 +272,7 @@ class SelectByTargetMeanPerformance(BaseSelector):
         self._confirm_variables(X)
 
         # find all variables or check those entered are present in the dataframe
-        self.variables_ = _find_all_variables(X, self.variables_, exclude_datetime=True)
+        self.variables_ = find_all_variables(X, self.variables_, exclude_datetime=True)
 
         if len(self.variables_) == 1 and self.threshold is None:
             raise ValueError(
diff --git a/feature_engine/timeseries/forecasting/base_forecast_transformers.py b/feature_engine/timeseries/forecasting/base_forecast_transformers.py
index c41ef4e..c724bdc 100644
--- a/feature_engine/timeseries/forecasting/base_forecast_transformers.py
+++ b/feature_engine/timeseries/forecasting/base_forecast_transformers.py
@@ -15,12 +15,6 @@ from feature_engine._docstrings.init_parameters.all_trasnformers import (
 )
 from feature_engine._docstrings.methods import _fit_not_learn_docstring
 from feature_engine._docstrings.substitute import Substitution
-from feature_engine._variable_handling.init_parameter_checks import (
-    _check_init_parameter_variables,
-)
-from feature_engine._variable_handling.variable_type_selection import (
-    _find_or_check_numerical_variables,
-)
 from feature_engine.dataframe_checks import (
     _check_contains_inf,
     _check_contains_na,
@@ -28,6 +22,12 @@ from feature_engine.dataframe_checks import (
     check_X,
 )
 from feature_engine.tags import _return_tags
+from feature_engine.variable_handling._init_parameter_checks import (
+    _check_init_parameter_variables,
+)
+from feature_engine.variable_handling.variable_type_selection import (
+    find_or_check_numerical_variables,
+)
 
 
 @Substitution(
@@ -155,7 +155,7 @@ class BaseForecastTransformer(BaseEstimator, TransformerMixin, GetFeatureNamesOu
         self._check_index(X)
 
         # find or check for numerical variables
-        self.variables_ = _find_or_check_numerical_variables(X, self.variables)
+        self.variables_ = find_or_check_numerical_variables(X, self.variables)
 
         # check if dataset contains na
         if self.missing_values == "raise":
diff --git a/feature_engine/timeseries/forecasting/expanding_window_features.py b/feature_engine/timeseries/forecasting/expanding_window_features.py
index 08d544e..3cabf01 100644
--- a/feature_engine/timeseries/forecasting/expanding_window_features.py
+++ b/feature_engine/timeseries/forecasting/expanding_window_features.py
@@ -2,6 +2,7 @@
 # License: BSD 3 clause
 
 from __future__ import annotations
+
 from typing import List
 
 import pandas as pd
diff --git a/feature_engine/timeseries/forecasting/lag_features.py b/feature_engine/timeseries/forecasting/lag_features.py
index 69fc46e..6abccb9 100644
--- a/feature_engine/timeseries/forecasting/lag_features.py
+++ b/feature_engine/timeseries/forecasting/lag_features.py
@@ -203,9 +203,7 @@ class LagFeatures(BaseForecastTransformer):
         # create the names for the lag features
         if isinstance(self.freq, list):
             feature_names = [
-                f"{feature}_lag_{fr}"
-                for fr in self.freq
-                for feature in self.variables_
+                f"{feature}_lag_{fr}" for fr in self.freq for feature in self.variables_
             ]
         elif self.freq is not None:
             feature_names = [
diff --git a/feature_engine/transformation/arcsin.py b/feature_engine/transformation/arcsin.py
index 75080c2..7dcad3a 100644
--- a/feature_engine/transformation/arcsin.py
+++ b/feature_engine/transformation/arcsin.py
@@ -21,10 +21,10 @@ from feature_engine._docstrings.methods import (
     _inverse_transform_docstring,
 )
 from feature_engine._docstrings.substitute import Substitution
-from feature_engine._variable_handling.init_parameter_checks import (
+from feature_engine.tags import _return_tags
+from feature_engine.variable_handling._init_parameter_checks import (
     _check_init_parameter_variables,
 )
-from feature_engine.tags import _return_tags
 
 
 @Substitution(
diff --git a/feature_engine/transformation/boxcox.py b/feature_engine/transformation/boxcox.py
index d3dc432..fa9de5c 100644
--- a/feature_engine/transformation/boxcox.py
+++ b/feature_engine/transformation/boxcox.py
@@ -21,10 +21,10 @@ from feature_engine._docstrings.methods import (
     _inverse_transform_docstring,
 )
 from feature_engine._docstrings.substitute import Substitution
-from feature_engine._variable_handling.init_parameter_checks import (
+from feature_engine.tags import _return_tags
+from feature_engine.variable_handling._init_parameter_checks import (
     _check_init_parameter_variables,
 )
-from feature_engine.tags import _return_tags
 
 
 @Substitution(
diff --git a/feature_engine/transformation/log.py b/feature_engine/transformation/log.py
index 7b7e2e2..2c1a466 100644
--- a/feature_engine/transformation/log.py
+++ b/feature_engine/transformation/log.py
@@ -22,10 +22,10 @@ from feature_engine._docstrings.methods import (
     _inverse_transform_docstring,
 )
 from feature_engine._docstrings.substitute import Substitution
-from feature_engine._variable_handling.init_parameter_checks import (
+from feature_engine.tags import _return_tags
+from feature_engine.variable_handling._init_parameter_checks import (
     _check_init_parameter_variables,
 )
-from feature_engine.tags import _return_tags
 
 
 @Substitution(
diff --git a/feature_engine/transformation/power.py b/feature_engine/transformation/power.py
index c9b7240..c318e1d 100644
--- a/feature_engine/transformation/power.py
+++ b/feature_engine/transformation/power.py
@@ -21,7 +21,7 @@ from feature_engine._docstrings.methods import (
     _inverse_transform_docstring,
 )
 from feature_engine._docstrings.substitute import Substitution
-from feature_engine._variable_handling.init_parameter_checks import (
+from feature_engine.variable_handling._init_parameter_checks import (
     _check_init_parameter_variables,
 )
 
diff --git a/feature_engine/transformation/reciprocal.py b/feature_engine/transformation/reciprocal.py
index 7fe869d..4ad3990 100644
--- a/feature_engine/transformation/reciprocal.py
+++ b/feature_engine/transformation/reciprocal.py
@@ -21,10 +21,10 @@ from feature_engine._docstrings.methods import (
     _inverse_transform_docstring,
 )
 from feature_engine._docstrings.substitute import Substitution
-from feature_engine._variable_handling.init_parameter_checks import (
+from feature_engine.tags import _return_tags
+from feature_engine.variable_handling._init_parameter_checks import (
     _check_init_parameter_variables,
 )
-from feature_engine.tags import _return_tags
 
 
 @Substitution(
diff --git a/feature_engine/transformation/yeojohnson.py b/feature_engine/transformation/yeojohnson.py
index 5d1f343..fb6b158 100644
--- a/feature_engine/transformation/yeojohnson.py
+++ b/feature_engine/transformation/yeojohnson.py
@@ -17,7 +17,7 @@ from feature_engine._docstrings.init_parameters.all_trasnformers import (
 )
 from feature_engine._docstrings.methods import _fit_transform_docstring
 from feature_engine._docstrings.substitute import Substitution
-from feature_engine._variable_handling.init_parameter_checks import (
+from feature_engine.variable_handling._init_parameter_checks import (
     _check_init_parameter_variables,
 )
 
diff --git a/feature_engine/variable_handling/__init__.py b/feature_engine/variable_handling/__init__.py
new file mode 100644
index 0000000..f6f214a
--- /dev/null
+++ b/feature_engine/variable_handling/__init__.py
@@ -0,0 +1,20 @@
+"""
+The module variable handling includes functions to select variables of a certain type
+or check that a list of variables is in certain type.
+"""
+
+from .variable_type_selection import (
+    find_all_variables,
+    find_categorical_and_numerical_variables,
+    find_or_check_categorical_variables,
+    find_or_check_datetime_variables,
+    find_or_check_numerical_variables,
+)
+
+__all__ = [
+    "find_all_variables",
+    "find_categorical_and_numerical_variables",
+    "find_or_check_categorical_variables",
+    "find_or_check_datetime_variables",
+    "find_or_check_numerical_variables",
+]
diff --git a/feature_engine/_variable_handling/init_parameter_checks.py b/feature_engine/variable_handling/_init_parameter_checks.py
similarity index 92%
rename from feature_engine/_variable_handling/init_parameter_checks.py
rename to feature_engine/variable_handling/_init_parameter_checks.py
index b8e8cde..dd0af1a 100644
--- a/feature_engine/_variable_handling/init_parameter_checks.py
+++ b/feature_engine/variable_handling/_init_parameter_checks.py
@@ -1,6 +1,6 @@
 from typing import Any
 
-from feature_engine._variable_handling.variable_type_selection import Variables
+from feature_engine.variable_handling.variable_type_selection import Variables
 
 
 # set return value typehint to Any to avoid issues with the base transformer fit method
diff --git a/feature_engine/_variable_handling/variable_type_checks.py b/feature_engine/variable_handling/_variable_type_checks.py
similarity index 100%
rename from feature_engine/_variable_handling/variable_type_checks.py
rename to feature_engine/variable_handling/_variable_type_checks.py
diff --git a/feature_engine/_variable_handling/variable_type_selection.py b/feature_engine/variable_handling/variable_type_selection.py
similarity index 59%
rename from feature_engine/_variable_handling/variable_type_selection.py
rename to feature_engine/variable_handling/variable_type_selection.py
index b97c9f3..8ffef38 100644
--- a/feature_engine/_variable_handling/variable_type_selection.py
+++ b/feature_engine/variable_handling/variable_type_selection.py
@@ -8,7 +8,7 @@ from pandas.api.types import is_datetime64_any_dtype as is_datetime
 from pandas.api.types import is_numeric_dtype as is_numeric
 from pandas.api.types import is_object_dtype as is_object
 
-from feature_engine._variable_handling.variable_type_checks import (
+from feature_engine.variable_handling._variable_type_checks import (
     _is_categorical_and_is_datetime,
     _is_categorical_and_is_not_datetime,
 )
@@ -16,28 +16,42 @@ from feature_engine._variable_handling.variable_type_checks import (
 Variables = Union[None, int, str, List[Union[str, int]]]
 
 
-def _find_or_check_numerical_variables(
+def find_or_check_numerical_variables(
     X: pd.DataFrame, variables: Variables = None
 ) -> List[Union[str, int]]:
     """
-    Checks that variables provided by the user are of type numerical. If None, finds
-    all the numerical variables in the DataFrame.
+    Returns the names of all the numerical variables in a dataframe. Alternatively, it
+    checks that the variables entered by the user are numerical.
+
+    More details in the :ref:`User Guide <find_num_vars>`.
 
     Parameters
     ----------
-    X : Pandas DataFrame.
-    variables : variable or list of variables. Defaults to None.
+    X : pandas dataframe of shape = [n_samples, n_features]
+        The dataset
 
-    Raises
-    ------
-    ValueError
-        If there are no numerical variables in the df or the df is empty.
-    TypeError
-        If any of the user provided variables are not numerical.
+    variables : list, default=None
+        If `None`, the function will return the names of all numerical variables in X.
+        Alternatively, it checks that the variables in the list are of type numerical.
 
     Returns
     -------
-    variables: List of numerical variables.
+    variables: List
+        The names of the numerical variables.
+
+    Examples
+    --------
+    >>> import pandas as pd
+    >>> from feature_engine.variable_handling import find_or_check_numerical_variables
+    >>> X = pd.DataFrame({
+    >>>     "var_num": [1, 2, 3],
+    >>>     "var_cat": ["A", "B", "C"],
+    >>>     "var_date": pd.date_range("2020-02-24", periods=3, freq="T")
+    >>> })
+    >>> var_num = find_or_check_numerical_variables(X)
+    >>> var_num
+
+    ['var_num']
     """
 
     if variables is None:
@@ -70,28 +84,48 @@ def _find_or_check_numerical_variables(
     return variables
 
 
-def _find_or_check_categorical_variables(
+def find_or_check_categorical_variables(
     X: pd.DataFrame, variables: Variables = None
 ) -> List[Union[str, int]]:
     """
-    Checks that variables provided by the user are of type object or categorical.
-    If None, finds all the categorical and object type variables in the DataFrame.
+    Returns the names of all the variables of type object or categorical in a dataframe.
+    Alternatively, it checks that the variables entered by the user are of type object
+    or categorical.
+
+    Note that when `variables` is `None`, the transformer will not select variables of
+    type object that can be parsed as datetime. But if the user passes a list with
+    datetime variables cast as object to the `variables` parameter, they will be
+    allowed.
+
+    More details in the :ref:`User Guide <find_cat_vars>`.
 
     Parameters
     ----------
-    X : pandas DataFrame.
-    variables : variable or list of variables. Defaults to None.
+    X : pandas dataframe of shape = [n_samples, n_features]
+        The dataset
 
-    Raises
-    ------
-    ValueError
-        If there are no categorical variables in df or df is empty.
-    TypeError
-        If any of the user provided variables are not categorical.
+    variables : list, default=None
+        If `None`, the function returns the names of all object or categorical variables
+        in X. Alternatively, it checks that the variables in the list are of type
+        object or categorical.
 
     Returns
     -------
-    variables : List of categorical variables.
+    variables: List
+        The names of the categorical variables.
+
+    Examples
+    --------
+    >>> import pandas as pd
+    >>> from feature_engine.variable_handling import find_or_check_categorical_variables
+    >>> X = pd.DataFrame({
+    >>>     "var_num": [1, 2, 3],
+    >>>     "var_cat": ["A", "B", "C"],
+    >>>     "var_date": pd.date_range("2020-02-24", periods=3, freq="T")
+    >>> })
+    >>> var_cat = find_or_check_categorical_variables(X)
+    >>> var_cat
+    ['var_cat']
     """
 
     if variables is None:
@@ -128,21 +162,47 @@ def _find_or_check_categorical_variables(
     return variables
 
 
-def _find_or_check_datetime_variables(
+def find_or_check_datetime_variables(
     X: pd.DataFrame, variables: Variables = None
 ) -> List[Union[str, int]]:
     """
-    Checks that variables provided by the user are of type datetime.
-    If None, finds all datetime variables in the DataFrame.
+    Returns the names of all the variables that are or can be parsed as datetime.
+    Alternatively, it checks that the variables entered by the user can be parsed as
+    datetime.
+
+    Note that this function will select variables cast as object if they can be cast as
+    datetime as well.
+
+    More details in the :ref:`User Guide <find_datetime_vars>`.
 
     Parameters
     ----------
-    X : pandas DataFrame
-    variables : variable or list of variables. Defaults to None.
+    X : pandas dataframe of shape = [n_samples, n_features]
+        The dataset
+
+    variables : list, default=None
+        If `None`, the function returns the names of all variables in X that can be
+        parsed as datetime. These include those cast as datetime, and also object and
+        categorical if they can be transformed to datetime variables. Alternatively, it
+        checks that the variables in the list are or can be parsed to datetime.
 
     Returns
     -------
-    variables : List of datetime variables.
+    variables: List
+        The names of the datetime variables.
+
+    Examples
+    --------
+    >>> import pandas as pd
+    >>> from feature_engine.variable_handling import find_or_check_datetime_variables
+    >>> X = pd.DataFrame({
+    >>>     "var_num": [1, 2, 3],
+    >>>     "var_cat": ["A", "B", "C"],
+    >>>     "var_date": pd.date_range("2020-02-24", periods=3, freq="T")
+    >>> })
+    >>> var_date = find_or_check_datetime_variables(X)
+    >>> var_date
+    ['var_date']
     """
 
     if variables is None:
@@ -184,29 +244,47 @@ def _find_or_check_datetime_variables(
     return variables
 
 
-def _find_all_variables(
+def find_all_variables(
     X: pd.DataFrame,
     variables: Variables = None,
     exclude_datetime: bool = False,
 ) -> List[Union[str, int]]:
     """
-    If variables are None, captures all variables in the dataframe in a list.
-    If user enters variable names in list, it returns the list.
+    Returns the names of all the variables in the dataframe in a list. Alternatively,
+    it will check that the variables indicated by the user are in the dataframe.
+
+    More details in the :ref:`User Guide <find_all_vars>`.
 
     Parameters
     ----------
-    X :  pandas DataFrame
-    variables : List of variables. Defaults to None.
+    X : pandas dataframe of shape = [n_samples, n_features]
+        The dataset
 
-    Raises
-    ------
-    TypeError
-        If the variable list provided by the user contains variables not present in the
+    variables : list, default=None
+        If `None`, the function will return the names of all the variables in X.
+        Alternatively, it checks that the variables in the list are present in the
         dataframe.
 
+    exclude_datetime: bool, default=False
+        Whether to exclude datetime variables.
+
     Returns
     -------
-    variables : List of numerical variables
+    variables: List
+        The names of the variables.
+
+    Examples
+    --------
+    >>> import pandas as pd
+    >>> from feature_engine.variable_handling import find_all_variables
+    >>> X = pd.DataFrame({
+    >>>     "var_num": [1, 2, 3],
+    >>>     "var_cat": ["A", "B", "C"],
+    >>>     "var_date": pd.date_range("2020-02-24", periods=3, freq="T")
+    >>> })
+    >>> vars_all = find_all_variables(X)
+    >>> vars_all
+    ['var_num', 'var_cat', 'var_date']
     """
     # find all variables in dataset
     if variables is None:
@@ -217,7 +295,7 @@ def _find_all_variables(
 
     elif isinstance(variables, (str, int)):
         if variables not in X.columns.to_list():
-            raise ValueError("The variable is not in the dataframe.")
+            raise ValueError(f"The variable {variables} is not in the dataframe.")
         variables_ = [variables]
 
     else:
@@ -273,21 +351,47 @@ def _filter_out_variables_not_in_dataframe(X, variables):
     return filtered_variables
 
 
-def _find_categorical_and_numerical_variables(
+def find_categorical_and_numerical_variables(
     X: pd.DataFrame, variables: Variables = None
 ) -> Tuple[List[Union[str, int]], List[Union[str, int]]]:
     """
     Find numerical and categorical variables.
 
+    The function returns two lists; the first one with the names of the variables of
+    type object or categorical and the second list with the names of the numerical
+    variables.
+
+    More details in the :ref:`User Guide <find_cat_and_num_vars>`.
+
     Parameters
     ----------
-    X :  pandas DataFrame
+    X : pandas dataframe of shape = [n_samples, n_features]
+        The dataset
 
-    variables : List of variables. Defaults to None.
+    variables : list, default=None
+        If `None`, the function will find categorical and numerical variables in X.
+        Alternatively, it will find categorical and numerical variables in the given
+        list.
 
     Returns
     -------
-    variables : Tuple with List of numerical and list of categorical variables.
+    variables: tuple
+        List of numerical and list of categorical variables.
+
+    Examples
+    --------
+    >>> import pandas as pd
+    >>> from feature_engine.variable_handling import (
+    >>>   find_categorical_and_numerical_variables
+    >>>)
+    >>> X = pd.DataFrame({
+    >>>     "var_num": [1, 2, 3],
+    >>>     "var_cat": ["A", "B", "C"],
+    >>>     "var_date": pd.date_range("2020-02-24", periods=3, freq="T")
+    >>> })
+    >>> var_cat, var_num = find_categorical_and_numerical_variables(X)
+    >>> var_cat, var_num
+    (['var_cat'], ['var_num'])
     """
 
     # If the user passes just 1 variable outside a list.
diff --git a/feature_engine/wrappers/wrappers.py b/feature_engine/wrappers/wrappers.py
index 7dec30a..de4e8aa 100644
--- a/feature_engine/wrappers/wrappers.py
+++ b/feature_engine/wrappers/wrappers.py
@@ -4,15 +4,15 @@ import pandas as pd
 from sklearn.base import BaseEstimator, TransformerMixin, clone
 from sklearn.utils.validation import check_is_fitted
 
-from feature_engine._variable_handling.init_parameter_checks import (
+from feature_engine.dataframe_checks import _check_X_matches_training_df, check_X
+from feature_engine.tags import _return_tags
+from feature_engine.variable_handling._init_parameter_checks import (
     _check_init_parameter_variables,
 )
-from feature_engine._variable_handling.variable_type_selection import (
-    _find_all_variables,
-    _find_or_check_numerical_variables,
+from feature_engine.variable_handling.variable_type_selection import (
+    find_all_variables,
+    find_or_check_numerical_variables,
 )
-from feature_engine.dataframe_checks import _check_X_matches_training_df, check_X
-from feature_engine.tags import _return_tags
 
 _SELECTORS = [
     "GenericUnivariateSelect",
@@ -219,10 +219,10 @@ class SklearnTransformerWrapper(BaseEstimator, TransformerMixin):
             "SimpleImputer",
             "FunctionTransformer",
         ]:
-            self.variables_ = _find_all_variables(X, self.variables)
+            self.variables_ = find_all_variables(X, self.variables)
 
         else:
-            self.variables_ = _find_or_check_numerical_variables(X, self.variables)
+            self.variables_ = find_or_check_numerical_variables(X, self.variables)
 
         self.transformer_.fit(X[self.variables_], y)
 


Test patch:
diff --git a/tests/test_selection/test_drop_duplicate_features.py b/tests/test_selection/test_drop_duplicate_features.py
index d461f50..5d33b3d 100644
--- a/tests/test_selection/test_drop_duplicate_features.py
+++ b/tests/test_selection/test_drop_duplicate_features.py
@@ -43,6 +43,23 @@ def df_duplicate_features_with_na():
     return df
 
 
+@pytest.fixture(scope="module")
+def df_duplicate_features_with_different_data_types():
+    data = {
+        "A": pd.Series([5.5] * 3).astype("float64"),
+        "B": 1,
+        "C": "foo",
+        "D": pd.Timestamp("20010102"),
+        "E": pd.Series([1.0] * 3).astype("float32"),
+        "F": False,
+        "G": pd.Series([1] * 3, dtype="int8"),
+    }
+
+    df = pd.DataFrame(data)
+
+    return df
+
+
 def test_drop_duplicates_features(df_duplicate_features):
     transformer = DropDuplicateFeatures()
     X = transformer.fit_transform(df_duplicate_features)
@@ -94,3 +111,18 @@ def test_with_df_with_na(df_duplicate_features_with_na):
         {"City", "City2"},
         {"Age", "Age2"},
     ]
+
+
+def test_with_different_data_types(df_duplicate_features_with_different_data_types):
+    transformer = DropDuplicateFeatures()
+    X = transformer.fit_transform(df_duplicate_features_with_different_data_types)
+    df = pd.DataFrame(
+        {
+            "A": pd.Series([5.5] * 3).astype("float64"),
+            "B": 1,
+            "C": "foo",
+            "D": pd.Timestamp("20010102"),
+            "F": False,
+        }
+    )
+    pd.testing.assert_frame_equal(X, df)
diff --git a/tests/test_variable_handling/test_init_parameter_checks.py b/tests/test_variable_handling/test_init_parameter_checks.py
index 3a8752c..23f3987 100644
--- a/tests/test_variable_handling/test_init_parameter_checks.py
+++ b/tests/test_variable_handling/test_init_parameter_checks.py
@@ -1,6 +1,6 @@
 import pytest
 
-from feature_engine._variable_handling.init_parameter_checks import (
+from feature_engine.variable_handling._init_parameter_checks import (
     _check_init_parameter_variables,
 )
 
diff --git a/tests/test_variable_handling/test_variable_type_selection.py b/tests/test_variable_handling/test_variable_type_selection.py
index 51ac6f0..cbd5532 100644
--- a/tests/test_variable_handling/test_variable_type_selection.py
+++ b/tests/test_variable_handling/test_variable_type_selection.py
@@ -1,13 +1,13 @@
 import pandas as pd
 import pytest
 
-from feature_engine._variable_handling.variable_type_selection import (
+from feature_engine.variable_handling.variable_type_selection import (
     _filter_out_variables_not_in_dataframe,
-    _find_all_variables,
-    _find_categorical_and_numerical_variables,
-    _find_or_check_categorical_variables,
-    _find_or_check_datetime_variables,
-    _find_or_check_numerical_variables,
+    find_all_variables,
+    find_categorical_and_numerical_variables,
+    find_or_check_categorical_variables,
+    find_or_check_datetime_variables,
+    find_or_check_numerical_variables,
 )
 
 
@@ -17,30 +17,30 @@ def test_find_or_check_numerical_variables(df_vartypes, df_numeric_columns):
     vars_mix = ["Age", "Marks", "Name"]
     vars_none = None
 
-    assert _find_or_check_numerical_variables(df_vartypes, vars_num) == vars_num
-    assert _find_or_check_numerical_variables(df_vartypes, var_num) == ["Age"]
-    assert _find_or_check_numerical_variables(df_vartypes, vars_none) == vars_num
+    assert find_or_check_numerical_variables(df_vartypes, vars_num) == vars_num
+    assert find_or_check_numerical_variables(df_vartypes, var_num) == ["Age"]
+    assert find_or_check_numerical_variables(df_vartypes, vars_none) == vars_num
 
     with pytest.raises(TypeError):
-        assert _find_or_check_numerical_variables(df_vartypes, "City")
+        assert find_or_check_numerical_variables(df_vartypes, "City")
 
     with pytest.raises(TypeError):
-        assert _find_or_check_numerical_variables(df_numeric_columns, 0)
+        assert find_or_check_numerical_variables(df_numeric_columns, 0)
 
     with pytest.raises(TypeError):
-        assert _find_or_check_numerical_variables(df_numeric_columns, [1, 3])
+        assert find_or_check_numerical_variables(df_numeric_columns, [1, 3])
 
     with pytest.raises(TypeError):
-        assert _find_or_check_numerical_variables(df_vartypes, vars_mix)
+        assert find_or_check_numerical_variables(df_vartypes, vars_mix)
 
     with pytest.raises(ValueError):
-        assert _find_or_check_numerical_variables(df_vartypes, variables=[])
+        assert find_or_check_numerical_variables(df_vartypes, variables=[])
 
     with pytest.raises(ValueError):
-        assert _find_or_check_numerical_variables(df_vartypes[["Name", "City"]], None)
+        assert find_or_check_numerical_variables(df_vartypes[["Name", "City"]], None)
 
-    assert _find_or_check_numerical_variables(df_numeric_columns, [2, 3]) == [2, 3]
-    assert _find_or_check_numerical_variables(df_numeric_columns, 2) == [2]
+    assert find_or_check_numerical_variables(df_numeric_columns, [2, 3]) == [2, 3]
+    assert find_or_check_numerical_variables(df_numeric_columns, 2) == [2]
 
 
 def _cast_var_as_type(df, var, new_type):
@@ -57,62 +57,62 @@ def test_find_or_check_categorical_variables(
 
     # errors when vars entered by user are not categorical
     with pytest.raises(TypeError):
-        assert _find_or_check_categorical_variables(df_vartypes, "Marks")
+        assert find_or_check_categorical_variables(df_vartypes, "Marks")
     with pytest.raises(TypeError):
-        assert _find_or_check_categorical_variables(df_datetime, "datetime_range")
+        assert find_or_check_categorical_variables(df_datetime, "datetime_range")
     with pytest.raises(TypeError):
-        assert _find_or_check_categorical_variables(df_datetime, ["datetime_range"])
+        assert find_or_check_categorical_variables(df_datetime, ["datetime_range"])
     with pytest.raises(TypeError):
-        assert _find_or_check_categorical_variables(df_numeric_columns, 3)
+        assert find_or_check_categorical_variables(df_numeric_columns, 3)
     with pytest.raises(TypeError):
-        assert _find_or_check_categorical_variables(df_numeric_columns, [0, 2])
+        assert find_or_check_categorical_variables(df_numeric_columns, [0, 2])
     with pytest.raises(TypeError):
-        assert _find_or_check_categorical_variables(df_vartypes, vars_mix)
+        assert find_or_check_categorical_variables(df_vartypes, vars_mix)
 
     # error when user enters empty list
     with pytest.raises(ValueError):
-        assert _find_or_check_categorical_variables(df_vartypes, variables=[])
+        assert find_or_check_categorical_variables(df_vartypes, variables=[])
 
     # error when df has no categorical variables
     with pytest.raises(ValueError):
-        assert _find_or_check_categorical_variables(df_vartypes[["Age", "Marks"]], None)
+        assert find_or_check_categorical_variables(df_vartypes[["Age", "Marks"]], None)
     with pytest.raises(ValueError):
-        assert _find_or_check_categorical_variables(
+        assert find_or_check_categorical_variables(
             df_datetime[["date_obj1", "time_obj"]], None
         )
 
     # when variables=None
-    assert _find_or_check_categorical_variables(df_vartypes, None) == vars_cat
-    assert _find_or_check_categorical_variables(df_datetime, None) == ["Name"]
+    assert find_or_check_categorical_variables(df_vartypes, None) == vars_cat
+    assert find_or_check_categorical_variables(df_datetime, None) == ["Name"]
 
     # when vars are specified
-    assert _find_or_check_categorical_variables(df_vartypes, "Name") == ["Name"]
-    assert _find_or_check_categorical_variables(df_datetime, "date_obj1") == [
+    assert find_or_check_categorical_variables(df_vartypes, "Name") == ["Name"]
+    assert find_or_check_categorical_variables(df_datetime, "date_obj1") == [
         "date_obj1"
     ]
-    assert _find_or_check_categorical_variables(df_vartypes, vars_cat) == vars_cat
-    assert _find_or_check_categorical_variables(df_datetime, ["Name", "date_obj1"]) == [
+    assert find_or_check_categorical_variables(df_vartypes, vars_cat) == vars_cat
+    assert find_or_check_categorical_variables(df_datetime, ["Name", "date_obj1"]) == [
         "Name",
         "date_obj1",
     ]
 
     # vars specified, column name is integer
-    assert _find_or_check_categorical_variables(df_numeric_columns, [0, 1]) == [0, 1]
-    assert _find_or_check_categorical_variables(df_numeric_columns, 0) == [0]
-    assert _find_or_check_categorical_variables(df_numeric_columns, 1) == [1]
+    assert find_or_check_categorical_variables(df_numeric_columns, [0, 1]) == [0, 1]
+    assert find_or_check_categorical_variables(df_numeric_columns, 0) == [0]
+    assert find_or_check_categorical_variables(df_numeric_columns, 1) == [1]
 
     # datetime vars cast as category
     # object-like datetime
     df_datetime["date_obj1"] = df_datetime["date_obj1"].astype("category")
-    assert _find_or_check_categorical_variables(df_datetime, None) == ["Name"]
-    assert _find_or_check_categorical_variables(df_datetime, ["Name", "date_obj1"]) == [
+    assert find_or_check_categorical_variables(df_datetime, None) == ["Name"]
+    assert find_or_check_categorical_variables(df_datetime, ["Name", "date_obj1"]) == [
         "Name",
         "date_obj1",
     ]
     # datetime64
     df_datetime["datetime_range"] = df_datetime["datetime_range"].astype("category")
-    assert _find_or_check_categorical_variables(df_datetime, None) == ["Name"]
-    assert _find_or_check_categorical_variables(
+    assert find_or_check_categorical_variables(df_datetime, None) == ["Name"]
+    assert find_or_check_categorical_variables(
         df_datetime, ["Name", "datetime_range"]
     ) == ["Name", "datetime_range"]
 
@@ -121,8 +121,8 @@ def test_find_or_check_categorical_variables(
         {"time_objTZ": df_datetime["time_obj"].add(["+5", "+11", "-3", "-8"])}
     )
     with pytest.raises(ValueError):
-        assert _find_or_check_categorical_variables(tz_time, None)
-    assert _find_or_check_categorical_variables(tz_time, "time_objTZ") == ["time_objTZ"]
+        assert find_or_check_categorical_variables(tz_time, None)
+    assert find_or_check_categorical_variables(tz_time, "time_objTZ") == ["time_objTZ"]
 
 
 @pytest.mark.parametrize(
@@ -133,13 +133,13 @@ def test_find_or_check_categorical_variables_when_numeric_is_cast_as_category_or
     df_vartypes, _num_var, _cat_type
 ):
     df_vartypes = _cast_var_as_type(df_vartypes, _num_var, _cat_type)
-    assert _find_or_check_categorical_variables(df_vartypes, _num_var) == [_num_var]
-    assert _find_or_check_categorical_variables(df_vartypes, None) == [
+    assert find_or_check_categorical_variables(df_vartypes, _num_var) == [_num_var]
+    assert find_or_check_categorical_variables(df_vartypes, None) == [
         "Name",
         "City",
         _num_var,
     ]
-    assert _find_or_check_categorical_variables(df_vartypes, ["Name", _num_var]) == [
+    assert find_or_check_categorical_variables(df_vartypes, ["Name", _num_var]) == [
         "Name",
         _num_var,
     ]
@@ -158,28 +158,28 @@ def test_find_or_check_datetime_variables(df_datetime):
 
     # error when df has no datetime variables
     with pytest.raises(ValueError):
-        assert _find_or_check_datetime_variables(
+        assert find_or_check_datetime_variables(
             df_datetime.loc[:, vars_nondt], variables=None
         )
 
     # errors when vars entered by user are not datetime
     with pytest.raises(TypeError):
-        assert _find_or_check_datetime_variables(df_datetime, variables="Age")
+        assert find_or_check_datetime_variables(df_datetime, variables="Age")
     with pytest.raises(TypeError):
-        assert _find_or_check_datetime_variables(df_datetime, variables=vars_nondt)
+        assert find_or_check_datetime_variables(df_datetime, variables=vars_nondt)
     with pytest.raises(TypeError):
-        assert _find_or_check_datetime_variables(df_datetime, variables=vars_mix)
+        assert find_or_check_datetime_variables(df_datetime, variables=vars_mix)
 
     # error when user enters empty list
     with pytest.raises(ValueError):
-        assert _find_or_check_datetime_variables(df_datetime, variables=[])
+        assert find_or_check_datetime_variables(df_datetime, variables=[])
 
     # when variables=None
     assert (
-        _find_or_check_datetime_variables(df_datetime, variables=None)
+        find_or_check_datetime_variables(df_datetime, variables=None)
         == vars_convertible_to_dt
     )
-    assert _find_or_check_datetime_variables(
+    assert find_or_check_datetime_variables(
         df_datetime[vars_convertible_to_dt].reindex(
             columns=["date_obj1", "datetime_range", "date_obj2"]
         ),
@@ -187,27 +187,27 @@ def test_find_or_check_datetime_variables(df_datetime):
     ) == ["date_obj1", "datetime_range", "date_obj2"]
 
     # when variables are specified
-    assert _find_or_check_datetime_variables(df_datetime, var_dt_str) == [var_dt_str]
-    assert _find_or_check_datetime_variables(df_datetime, var_dt) == var_dt
-    assert _find_or_check_datetime_variables(
+    assert find_or_check_datetime_variables(df_datetime, var_dt_str) == [var_dt_str]
+    assert find_or_check_datetime_variables(df_datetime, var_dt) == var_dt
+    assert find_or_check_datetime_variables(
         df_datetime, variables=var_convertible_to_dt
     ) == [var_convertible_to_dt]
     assert (
-        _find_or_check_datetime_variables(df_datetime, variables=vars_convertible_to_dt)
+        find_or_check_datetime_variables(df_datetime, variables=vars_convertible_to_dt)
         == vars_convertible_to_dt
     )
-    assert _find_or_check_datetime_variables(
+    assert find_or_check_datetime_variables(
         df_datetime.join(tz_time),
         variables=None,
     ) == vars_convertible_to_dt + ["time_objTZ"]
 
     # datetime var cast as categorical
     df_datetime["date_obj1"] = df_datetime["date_obj1"].astype("category")
-    assert _find_or_check_datetime_variables(df_datetime, variables="date_obj1") == [
+    assert find_or_check_datetime_variables(df_datetime, variables="date_obj1") == [
         "date_obj1"
     ]
     assert (
-        _find_or_check_datetime_variables(df_datetime, variables=vars_convertible_to_dt)
+        find_or_check_datetime_variables(df_datetime, variables=vars_convertible_to_dt)
         == vars_convertible_to_dt
     )
 
@@ -218,15 +218,13 @@ def test_find_or_check_datetime_variables_when_numeric_is_cast_as_category_or_ob
 ):
     df_datetime = _cast_var_as_type(df_datetime, _num_var, _cat_type)
     with pytest.raises(TypeError):
-        assert _find_or_check_datetime_variables(df_datetime, variables=_num_var)
+        assert find_or_check_datetime_variables(df_datetime, variables=_num_var)
     with pytest.raises(TypeError):
-        assert _find_or_check_datetime_variables(df_datetime, variables=[_num_var])
+        assert find_or_check_datetime_variables(df_datetime, variables=[_num_var])
     with pytest.raises(ValueError) as errinfo:
-        assert _find_or_check_datetime_variables(
-            df_datetime[[_num_var]], variables=None
-        )
+        assert find_or_check_datetime_variables(df_datetime[[_num_var]], variables=None)
     assert str(errinfo.value) == "No datetime variables found in this dataframe."
-    assert _find_or_check_datetime_variables(df_datetime, variables=None) == [
+    assert find_or_check_datetime_variables(df_datetime, variables=None) == [
         "datetime_range",
         "date_obj1",
         "date_obj2",
@@ -240,12 +238,12 @@ def test_find_all_variables(df_vartypes):
     user_vars = ["Name", "City"]
     non_existing_vars = ["Grades"]
 
-    assert _find_all_variables(df_vartypes) == all_vars
-    assert _find_all_variables(df_vartypes, exclude_datetime=True) == all_vars_no_dt
-    assert _find_all_variables(df_vartypes, ["Name", "City"]) == user_vars
+    assert find_all_variables(df_vartypes) == all_vars
+    assert find_all_variables(df_vartypes, exclude_datetime=True) == all_vars_no_dt
+    assert find_all_variables(df_vartypes, ["Name", "City"]) == user_vars
 
     with pytest.raises(KeyError):
-        assert _find_all_variables(df_vartypes, non_existing_vars)
+        assert find_all_variables(df_vartypes, non_existing_vars)
 
 
 filter_dict = [
@@ -273,58 +271,56 @@ def test_filter_out_variables_not_in_dataframe(df, variables, overlap, not_in_co
 def test_find_categorical_and_numerical_variables(df_vartypes):
 
     # Case 1: user passes 1 variable that is categorical
-    assert _find_categorical_and_numerical_variables(df_vartypes, ["Name"]) == (
+    assert find_categorical_and_numerical_variables(df_vartypes, ["Name"]) == (
         ["Name"],
         [],
     )
-    assert _find_categorical_and_numerical_variables(df_vartypes, "Name") == (
+    assert find_categorical_and_numerical_variables(df_vartypes, "Name") == (
         ["Name"],
         [],
     )
 
     # Case 2: user passes 1 variable that is numerical
-    assert _find_categorical_and_numerical_variables(df_vartypes, ["Age"]) == (
+    assert find_categorical_and_numerical_variables(df_vartypes, ["Age"]) == (
         [],
         ["Age"],
     )
-    assert _find_categorical_and_numerical_variables(df_vartypes, "Age") == (
+    assert find_categorical_and_numerical_variables(df_vartypes, "Age") == (
         [],
         ["Age"],
     )
 
     # Case 3: user passes 1 categorical and 1 numerical variable
-    assert _find_categorical_and_numerical_variables(df_vartypes, ["Age", "Name"]) == (
+    assert find_categorical_and_numerical_variables(df_vartypes, ["Age", "Name"]) == (
         ["Name"],
         ["Age"],
     )
 
     # Case 4: automatically identify variables
-    assert _find_categorical_and_numerical_variables(df_vartypes, None) == (
+    assert find_categorical_and_numerical_variables(df_vartypes, None) == (
         ["Name", "City"],
         ["Age", "Marks"],
     )
-    assert _find_categorical_and_numerical_variables(
+    assert find_categorical_and_numerical_variables(
         df_vartypes[["Name", "City"]], None
     ) == (["Name", "City"], [])
-    assert _find_categorical_and_numerical_variables(
+    assert find_categorical_and_numerical_variables(
         df_vartypes[["Age", "Marks"]], None
     ) == ([], ["Age", "Marks"])
 
     # Case 5: error when no variable is numerical or categorical
     with pytest.raises(TypeError):
-        _find_categorical_and_numerical_variables(df_vartypes["dob"].to_frame(), None)
+        find_categorical_and_numerical_variables(df_vartypes["dob"].to_frame(), None)
 
     with pytest.raises(TypeError):
-        _find_categorical_and_numerical_variables(
-            df_vartypes["dob"].to_frame(), ["dob"]
-        )
+        find_categorical_and_numerical_variables(df_vartypes["dob"].to_frame(), ["dob"])
 
     with pytest.raises(TypeError):
-        _find_categorical_and_numerical_variables(df_vartypes["dob"].to_frame(), "dob")
+        find_categorical_and_numerical_variables(df_vartypes["dob"].to_frame(), "dob")
 
     # Case 6: user passes empty list
     with pytest.raises(ValueError):
-        _find_categorical_and_numerical_variables(df_vartypes, [])
+        find_categorical_and_numerical_variables(df_vartypes, [])
 
     # Case 7: datetime cast as object
     df = df_vartypes.copy()
@@ -332,11 +328,11 @@ def test_find_categorical_and_numerical_variables(df_vartypes):
 
     # datetime variable is skipped when automatically finding variables, but
     # selected if user passes it in list
-    assert _find_categorical_and_numerical_variables(df, None) == (
+    assert find_categorical_and_numerical_variables(df, None) == (
         ["Name", "City"],
         ["Age", "Marks"],
     )
-    assert _find_categorical_and_numerical_variables(df, ["Name", "Marks", "dob"]) == (
+    assert find_categorical_and_numerical_variables(df, ["Name", "Marks", "dob"]) == (
         ["Name", "dob"],
         ["Marks"],
     )
@@ -344,8 +340,8 @@ def test_find_categorical_and_numerical_variables(df_vartypes):
     # Case 8: variables cast as category
     df = df_vartypes.copy()
     df["City"] = df["City"].astype("category")
-    assert _find_categorical_and_numerical_variables(df, None) == (
+    assert find_categorical_and_numerical_variables(df, None) == (
         ["Name", "City"],
         ["Age", "Marks"],
     )
-    assert _find_categorical_and_numerical_variables(df, "City") == (["City"], [])
+    assert find_categorical_and_numerical_variables(df, "City") == (["City"], [])