Source code for datamop.column_scaler

# Formula in this function is adapted from Scikit Learn documentation
# https://scikit-learn.org/1.5/modules/generated/sklearn.preprocessing.MinMaxScaler.html
# https://scikit-learn.org/1.6/modules/generated/sklearn.preprocessing.StandardScaler.html

import pandas as pd
import numpy as np
import warnings

[docs] def column_scaler(data, column, method="minmax", new_min=0, new_max=1, inplace=True): """ Scales the values of a specified column in a DataFrame. Parameters ----------- data : pandas.DataFrame The DataFrame containing the column of interest for scaling. column: str The name of the numeric column to scale. method: str The method used for scaling. Options include: - `minmax`: Scales values between `new_min` and `new_max`, used as default method. - `standard`: Scales values with mean of 0 and standard deviation of 1. new_min: float The lower boundary value for min-max scaling. Default value is 0. new_max: float The upper boundary value for min-max scaling. Default value is 1. inplace: bool If `True` the original column is replaced with new scaled values. If `False` the original column is retained and the new scaled column is added to the dataframe with title `<column-name>-scaled`. Default is True. Returns -------- pandas.DataFrame A copy of the DataFrame with the scaled column replacing the original column if `inplace` is set to `True`. If `inplace` is set to `False`, the copy of DataFrame is returned with the new scaled column added, keeping the original column. Raises ------ TypeError If the input `data` is not a pandas DataFrame. KeyError: If the column passed for scaling does not exist in the DataFrame. ValueError: If the column passed for scaling is not numeric. If the `method` is not `minmax` or `standard`. If the `new_min` value is greater or equal to the `new_max` when using `minmax` method. Examples -------- >>> import pandas as pd >>> df = pd.DataFrame({"price": [25, 50, 75]}) >>> df_scaled = column_scaler(df, column = 'price', method='minmax', new_min=0, new_max=1) >>> print(df_scaled) price 0.0 0.5 1.0 """ # Check input is pd.DataFrame if not isinstance(data, pd.DataFrame): raise TypeError("Input must be a pandas DataFrame.") # Empty df warning if data.empty: warnings.warn( "Empty DataFrame detected. Empty DataFrame will be returned.", UserWarning ) return data.copy() # Error handling if column not in data.columns: raise KeyError("Column not found in the DataFrame.") if not pd.api.types.is_numeric_dtype(data[column]): raise ValueError("Column must have numeric values.") if method not in {"minmax", "standard"}: raise ValueError("Invalid method. Method should be `minmax` or `standard`.") # Edge case warning if data[column].isna().any(): warnings.warn( f"NaN value detected in column '{column}'. They will be unchanged", UserWarning ) if data[column].nunique() == 1: if method == "minmax": warnings.warn( "Single-value column detected. " "All values will be scaled to the midpoint of the `new_min` and `new_max`.", UserWarning ) midpoint = (new_min + new_max) / 2 scaled_column = pd.Series([midpoint] * len(data), index=data.index) elif method == "standard": warnings.warn( "Standard deviation is zero. " "All values are set to 0 to prevent division by zero.", UserWarning ) scaled_column = pd.Series([0] * len(data), index=data.index) # Scale the column else: # minmax scaling if method == "minmax": if new_min >= new_max: raise ValueError("`new_min` cannot be greater than `new_max`.") min_value = data[column].min() max_value = data[column].max() scaled_column = ( ((data[column] - min_value) / (max_value - min_value)) * (new_max - new_min) + new_min ) # standard scaling elif method == "standard": mean_value = data[column].mean() std_value = data[column].std() scaled_column = (data[column] - mean_value) / std_value # Return df with scaled column if inplace: data[column] = scaled_column return data else: scaled_column_name = f"{column}_scaled" data[scaled_column_name] = scaled_column return data