I'd like to propose adding a function to calculate Variance Inflation Factors (VIFs) for assessing multicollinearity among predictor variables. While statsmodels provides this functionality, the current implementation requires unnecessary boilerplate (in my opinion) to extract VIF values across all predictors:
from statsmodels.stats.outliers_influence import variance_inflation_factor
vif_ratios = []
for idx in range(df_num.shape[1]):
vif_ratios.append(variance_inflation_factor(arr, idx))
In my view, the main limitations of this approach are:
- Column name mapping - since most data analysis workflows use
pandas DataFrames, additional code is needed to associate VIF values with their corresponding column names.
- Missing data - the function does not handle missing values natively and raises a
MissingDataError if any are present.
- Categorical columns - categorical variables are not handled natively and must be excluded manually before calling the function.
I propose a wrapper function with the following behaviour:
- Accepts both
pandas DataFrames and numpy arrays as input.
- Automatically removes rows containing missing values.
- Discards categorical columns when the input is a
pandas DataFrame.
- Returns a
pandas DataFrame with VIF values per column (when the input is a DataFrame), or a numpy array of VIF values in the original column order (when the input is an array).
- Optionally, accepts a threshold parameter to flag column names or indices where the VIF exceeds a user-defined value.
In my private repository, I've implemented previously a function that does some of the above (the below is just for demonstration, it would require to be expanded in terms of functionality):
def vif(df):
"""
Compute Variance Inflation Factor (VIF) for each numeric variable. Low values
indicate low multicollinearity.
Parameters
----------
df : DataFrame
Input DataFrame containing the variables to assess. Non-numeric columns
are ignored automatically and rows with any NaN values and constante values
are dropped before computation.
Returns
-------
DataFrame
Single-row DataFrame with the VIF for each numerical variable.
"""
# get numeric columns, remove columns with constant and nan values
df_num = df.select_dtypes("number").copy()
df_num = df_num.dropna(axis=0, how="any")
df_num = df_num.loc[:, df_num.nunique() > 1]
if df_num.empty:
raise ValueError("preprocessing made the input DataFrame empty")
# estimate VIF for each variable
vif_ratios = []
for idx in range(df_num.shape[1]):
vif_ratios.append(variance_inflation_factor(arr, idx))
# convert vif_ratios to DataFrame
return pd.DataFrame([vif_ratios], columns=df_num.columns, index=["VIF"])
I'd like to propose adding a function to calculate Variance Inflation Factors (VIFs) for assessing multicollinearity among predictor variables. While statsmodels provides this functionality, the current implementation requires unnecessary boilerplate (in my opinion) to extract VIF values across all predictors:
In my view, the main limitations of this approach are:
pandasDataFrames, additional code is needed to associate VIF values with their corresponding column names.MissingDataErrorif any are present.I propose a wrapper function with the following behaviour:
pandasDataFrames andnumpyarrays as input.pandasDataFrame.pandasDataFrame with VIF values per column (when the input is a DataFrame), or a numpy array of VIF values in the original column order (when the input is an array).In my private repository, I've implemented previously a function that does some of the above (the below is just for demonstration, it would require to be expanded in terms of functionality):