如何在Python中系统地删除共线变量?[关闭]


18

到目前为止,我已经通过查看相关表并消除了超过某个阈值的变量,来删除了共线变量作为数据准备过程的一部分。有一种更可接受的方式吗?此外,我知道一次只查看两个变量之间的相关性并不理想,像VIF这样的测量考虑了多个变量之间的潜在相关性。如何系统地选择不表现出多重共线性的变量组合?

我将数据存储在熊猫数据框中,并且正在使用sklearn的模型。


3
您可能要考虑偏最小二乘回归或主成分回归。其中之一可能受支持。
spdrnl

我知道了。因此,如果我理解正确,那么运行PCA会给我一组独立的主成分,然后将其用作模型的协变量,因为每个主成分都不与其他共线性?
orange1 2015年

2
究竟。某些组件可能变得无关紧要。这比删除变量更容易。
spdrnl

嗯,所以我的目的主要是为了解释性目的而不是预测性目的运行模型。如何解释将主成分用作协变量的模型?
orange1 2015年

1
在这种情况下,这无济于事,因为解释组件在某种程度上是一门黑手艺。
spdrnl 2015年

Answers:


13

谢谢SpanishBoy-这是一段不错的代码。@ilanman:这将检查VIF值,然后删除VIF大于5的变量。“性能”我认为他表示运行时间。上面的代码花了我大约3个小时来运行大约300个变量,5000行。

顺便说一下,我已经对其进行了修改,以删除一些额外的循环。另外,我使它变得更整洁,并返回带有减少变量的数据框。这个版本将我的运行时间减少了一半!我的代码如下-希望对您有所帮助。

from statsmodels.stats.outliers_influence import variance_inflation_factor    

def calculate_vif_(X, thresh=5.0):
    variables = list(range(X.shape[1]))
    dropped = True
    while dropped:
        dropped = False
        vif = [variance_inflation_factor(X.iloc[:, variables].values, ix)
               for ix in range(X.iloc[:, variables].shape[1])]

        maxloc = vif.index(max(vif))
        if max(vif) > thresh:
            print('dropping \'' + X.iloc[:, variables].columns[maxloc] +
                  '\' at index: ' + str(maxloc))
            del variables[maxloc]
            dropped = True

    print('Remaining variables:')
    print(X.columns[variables])
    return X.iloc[:, variables]

谢谢。您是否比较了两个函数的输出?我看到了VIF 的R函数(包装usdm方法vifstep),运行时真的很棒。正如我之前说过的,上面的变体和您的变量(优化了一半)与R相比太慢了。还有其他想法如何优化吗?
SpanishBoy

1
我对这种方法有疑问。假设我们具有A,B和C功能。A与C相关联。如果您遍历功能,则A和C的VIF> 5,因此将其删除。实际上,您不应在每次删除功能后重新计算VIF。在我的示例中,您同时删除了A和C,但是如果在删除A之后计算VIF(C),则不会> 5
Titus Pullo

3

您可以尝试使用以下代码:

from statsmodels.stats.outliers_influence import variance_inflation_factor

def calculate_vif_(X):

    '''X - pandas dataframe'''
    thresh = 5.0
    variables = range(X.shape[1])

    for i in np.arange(0, len(variables)):
        vif = [variance_inflation_factor(X[variables].values, ix) for ix in range(X[variables].shape[1])]
        print(vif)
        maxloc = vif.index(max(vif))
        if max(vif) > thresh:
            print('dropping \'' + X[variables].columns[maxloc] + '\' at index: ' + str(maxloc))
            del variables[maxloc]

    print('Remaining variables:')
    print(X.columns[variables])
    return X

它有效,但我不喜欢这种方法的效果


您想对这种方法做什么发表更多评论吗?还有为什么您不喜欢这种表演?
ilanman

2

我尝试了SpanishBoy的答案,并在为数据帧运行它时发现服务器错误。这是一个调试的解决方案。

from statsmodels.stats.outliers_influence import variance_inflation_factor    

def calculate_vif_(X, thresh=100):
cols = X.columns
variables = np.arange(X.shape[1])
dropped=True
while dropped:
    dropped=False
    c = X[cols[variables]].values
    vif = [variance_inflation_factor(c, ix) for ix in np.arange(c.shape[1])]

    maxloc = vif.index(max(vif))
    if max(vif) > thresh:
        print('dropping \'' + X[cols[variables]].columns[maxloc] + '\' at index: ' + str(maxloc))
        variables = np.delete(variables, maxloc)
        dropped=True

print('Remaining variables:')
print(X.columns[variables])
return X[cols[variables]]

我也没有任何性能问题,但是还没有对其进行广泛的测试。


这很好,对我有用。除外,它返回了不祥的警告:RuntimeWarning: divide by zero encountered in double_scalars
user2205916 '18
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.