gpt4 book ai didi

python - Python中的方差膨胀因子

转载 作者:IT老高 更新时间:2023-10-28 21:07:00 28 4
gpt4 key购买 nike

我正在尝试计算 python 中一个简单数据集中每一列的方差膨胀因子 (VIF):

a b c d
1 2 4 4
1 2 6 3
2 3 7 4
3 2 8 5
4 1 9 4

我已经在 R 中使用 usdm library 中的 vif 函数完成了这项工作。结果如下:

a <- c(1, 1, 2, 3, 4)
b <- c(2, 2, 3, 2, 1)
c <- c(4, 6, 7, 8, 9)
d <- c(4, 3, 4, 5, 4)

df <- data.frame(a, b, c, d)
vif_df <- vif(df)
print(vif_df)

Variables VIF
a 22.95
b 3.00
c 12.95
d 3.00

但是,当我在 python 中使用 statsmodel vif function 执行相同操作时,我的结果是:

a = [1, 1, 2, 3, 4]
b = [2, 2, 3, 2, 1]
c = [4, 6, 7, 8, 9]
d = [4, 3, 4, 5, 4]

ck = np.column_stack([a, b, c, d])

vif = [variance_inflation_factor(ck, i) for i in range(ck.shape[1])]
print(vif)

Variables VIF
a 47.136986301369774
b 28.931506849315081
c 80.31506849315096
d 40.438356164383549

即使输入相同,结果也大不相同。一般来说,statsmodel VIF 函数的结果似乎是错误的,但我不确定这是因为我调用它的方式还是函数本身的问题。

我希望有人可以帮助我弄清楚我是否错误地调用了 statsmodel 函数或解释结果中的差异。如果是函数的问题,那么 python 中是否有任何 VIF 替代方案?

最佳答案

正如其他人在 this post 中提到的那样通过函数作者 Josef Perktold,variance_inflation_factor 期望解释变量矩阵中存在一个常数。可以使用 statsmodels 中的 add_constant 将所需的常量添加到数据帧中,然后再将其值传递给函数。

from statsmodels.stats.outliers_influence import variance_inflation_factor
from statsmodels.tools.tools import add_constant

df = pd.DataFrame(
{'a': [1, 1, 2, 3, 4],
'b': [2, 2, 3, 2, 1],
'c': [4, 6, 7, 8, 9],
'd': [4, 3, 4, 5, 4]}
)

X = add_constant(df)
>>> pd.Series([variance_inflation_factor(X.values, i)
for i in range(X.shape[1])],
index=X.columns)
const 136.875
a 22.950
b 3.000
c 12.950
d 3.000
dtype: float64

我相信您也可以使用 assign 将常量添加到数据框的最右侧列:

X = df.assign(const=1)
>>> pd.Series([variance_inflation_factor(X.values, i)
for i in range(X.shape[1])],
index=X.columns)
a 22.950
b 3.000
c 12.950
d 3.000
const 136.875
dtype: float64

源代码本身比较简洁:

def variance_inflation_factor(exog, exog_idx):
"""
exog : ndarray, (nobs, k_vars)
design matrix with all explanatory variables, as for example used in
regression
exog_idx : int
index of the exogenous variable in the columns of exog
"""
k_vars = exog.shape[1]
x_i = exog[:, exog_idx]
mask = np.arange(k_vars) != exog_idx
x_noti = exog[:, mask]
r_squared_i = OLS(x_i, x_noti).fit().rsquared
vif = 1. / (1. - r_squared_i)
return vif

修改代码以将所有 VIF 作为一个系列返回也相当简单:

from statsmodels.regression.linear_model import OLS
from statsmodels.tools.tools import add_constant

def variance_inflation_factors(exog_df):
'''
Parameters
----------
exog_df : dataframe, (nobs, k_vars)
design matrix with all explanatory variables, as for example used in
regression.

Returns
-------
vif : Series
variance inflation factors
'''
exog_df = add_constant(exog_df)
vifs = pd.Series(
[1 / (1. - OLS(exog_df[col].values,
exog_df.loc[:, exog_df.columns != col].values).fit().rsquared)
for col in exog_df],
index=exog_df.columns,
name='VIF'
)
return vifs

>>> variance_inflation_factors(df)
const 136.875
a 22.950
b 3.000
c 12.950
Name: VIF, dtype: float64

根据@T_T的解决方案,也可以简单地做以下事情:

vifs = pd.Series(np.linalg.inv(df.corr().to_numpy()).diagonal(), 
index=df.columns,
name='VIF')

关于python - Python中的方差膨胀因子,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42658379/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com