Repository: pyjanitor-devs/pyjanitor

Issue:
[EHN] Add `jointly` option for `min_max_scale`
<!-- Thank you for your PR!

BEFORE YOU CONTINUE! Please add the appropriate three-letter abbreviation to your title.

The abbreviations can be:
- [DOC]: Documentation fixes.
- [ENH]: Code contributions and new features.
- [TST]: Test-related contributions.
- [INF]: Infrastructure-related contributions.

Also, do not forget to tag the relevant issue here as well.

Finally, as commits come in, don't forget to regularly rebase!
-->

# PR Description

Please describe the changes proposed in the pull request:

- Add an option for `min_max_scale` support to transform each column values or entire values
- Default transform each column, similar behavior to [sklearn.preprocessing.MinMaxScaler](http://scikit-learn.org/stable/modules/generated/sklearn.preprocessing.MinMaxScaler.html)

<!-- Doing so provides maintainers with context on what the PR is, and can help us more effectively review your PR. -->

<!-- Please also identify below which issue that has been raised that you are going to close. -->

**This PR resolves #1067.**

<!-- As you go down the PR template, please feel free to delete sections that are irrelevant. -->

# PR Checklist

<!-- This checklist exists for newcomers who are not yet familiar with our requirements. If you are experienced with
the project, please feel free to delete this section. -->

Please ensure that you have done the following:

1. [x] PR in from a fork off your branch. Do not PR from `<your_username>`:`dev`, but rather from `<your_username>`:`<feature-branch_name>`.
<!-- Doing this helps us keep the commit history much cleaner than it would otherwise be. -->
2. [x] If you're not on the contributors list, add yourself to `AUTHORS.md`.
<!-- We'd like to acknowledge your contributions! -->
3. [x] Add a line to `CHANGELOG.md` under the latest version header (i.e. the one that is "on deck") describing the contribution.
    - Do use some discretion here; if there are multiple PRs that are related, keep them in a single line.

# Automatic checks

There will be automatic checks run on the PR. These include:

- Building a preview of the docs on Netlify
- Automatically linting the code
- Making sure the code is documented
- Making sure that all tests are passed
- Making sure that code coverage doesn't go down.

# Relevant Reviewers

<!-- Finally, please tag relevant maintainers to review. -->

Please tag maintainers to review.

- @ericmjl



Discussion:
# [Codecov](https://codecov.io/gh/pyjanitor-devs/pyjanitor/pull/1112?src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=pyjanitor-devs) Report
> Merging [#1112](https://codecov.io/gh/pyjanitor-devs/pyjanitor/pull/1112?src=pr&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=pyjanitor-devs) (eff218b) into [dev](https://codecov.io/gh/pyjanitor-devs/pyjanitor/commit/245012443d01247a591fd0e931b154c7a12a9753?el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=pyjanitor-devs) (2450124) will **increase** coverage by `0.03%`.
> The diff coverage is `100.00%`.


```diff
@@            Coverage Diff             @@
##              dev    #1112      +/-   ##
==========================================
+ Coverage   97.95%   97.98%   +0.03%     
==========================================
  Files          77       77              
  Lines        3175     3180       +5     
==========================================
+ Hits         3110     3116       +6     
+ Misses         65       64       -1     
```

Well, GitHub Action style checking is failing but pre-commit.ci app is okay.
I thought it was time to cut the duplicate style checkings #1113

![image](https://user-images.githubusercontent.com/25895405/171585622-e0ebcea5-bcb8-4b6c-9660-0a289b5542a9.png)

@Zeroto521 looks like we're good. The action didn't fail b/c of your code; it failed b/c of a system error.

Resolving patch:
diff --git a/janitor/functions/min_max_scale.py b/janitor/functions/min_max_scale.py
--- a/janitor/functions/min_max_scale.py
+++ b/janitor/functions/min_max_scale.py
@@ -96,6 +96,12 @@ def min_max_scale(
     1 to 14. Hence, 3 gets scaled not to 0 but approx. 0.15 instead, while 10
     gets scaled to approx. 0.69 instead.
 
+    !!! summary "Version Changed"
+
+        - 0.24.0
+            - Deleted `old_min`, `old_max`, `new_min`, and `new_max` options.
+            - Added `feature_range`, and `jointly` options.
+
     :param df: A pandas DataFrame.
     :param feature_range: (optional) Desired range of transformed data.
     :param column_name: (optional) The column on which to perform scaling.
@@ -105,10 +111,6 @@ def min_max_scale(
     :raises ValueError: if the length of `feature_range` isn't equal to two.
     :raises ValueError: if the element of `feature_range` isn't number type.
     :raises ValueError: if `feature_range[1]` <= `feature_range[0]`.
-
-    Changed in version 0.24.0: Deleted "old_min", "old_max", "new_min", and
-    "new_max" options.
-    Changed in version 0.24.0: Added "feature_range", and "jointly" options.
     """
 
     if not (
@@ -125,16 +127,16 @@ def min_max_scale(
     if column_name is not None:
         df = df.copy()  # Avoid to change the original DataFrame.
 
-        old_feature_range = df[column_name].pipe(min_max_value, jointly)
+        old_feature_range = df[column_name].pipe(_min_max_value, jointly)
         df[column_name] = df[column_name].pipe(
-            apply_min_max,
+            _apply_min_max,
             *old_feature_range,
             *feature_range,
         )
     else:
-        old_feature_range = df.pipe(min_max_value, jointly)
+        old_feature_range = df.pipe(_min_max_value, jointly)
         df = df.pipe(
-            apply_min_max,
+            _apply_min_max,
             *old_feature_range,
             *feature_range,
         )
@@ -142,7 +144,7 @@ def min_max_scale(
     return df
 
 
-def min_max_value(df: pd.DataFrame, jointly: bool) -> tuple:
+def _min_max_value(df: pd.DataFrame, jointly: bool) -> tuple:
     """
     Return the minimum and maximum of DataFrame.
 
@@ -162,7 +164,7 @@ def min_max_value(df: pd.DataFrame, jointly: bool) -> tuple:
     return mmin, mmax
 
 
-def apply_min_max(
+def _apply_min_max(
     df: pd.DataFrame,
     old_min: int | float | pd.Series,
     old_max: int | float | pd.Series,


Test patch: