Фактор инфляции дисперсии в Python

Я пытаюсь рассчитать фактор инфляции дисперсии (VIF) для каждого столбца в простом наборе данных на Python.

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 с помощью функции vif из [библиотеки usdm](https://cran.r-project.org/web/packages/usdm/usdm.pdf), что дало следующие результаты:
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, используя функцию VIF в statsmodel, мои результаты следующие:

Полученные результаты существенно различаются, хотя входные данные одинаковы. Как правило, результаты, полученные с использованием функции VIF из пакета statsmodel, кажутся неверными, но я не уверен, связано ли это с тем, как я вызываю эту функцию, или это проблема самой функции.

Я надеялся, что кто-нибудь сможет помочь мне понять, неправильно ли я вызывал функцию statsmodel или объяснить расхождения в результатах. Если это проблема с функцией, то есть ли альтернативы VIF на Python?

Как упоминалось другими и в этом посте от автора функции Йозефа Перктольда, функция variance_inflation_factor требует наличия константы в матрице объясняющих переменных. Можно использовать add_constant из statsmodels, чтобы добавить необходимую константу к датафрейму перед передачей его значений в функцию.

Я верю, вы также можете добавить константу в крайнюю правую колонку dataframe, используя

Исходный код довольно лаконичный:

Также довольно просто изменить код, чтобы вернуть все VIF в виде серии:

Согласно решению @T_T, можно также просто сделать следующее:

Я считаю, что причина этого заключается в отличии OLS в Python. OLS, который используется при расчете фактора инфляции дисперсии в Python, по умолчанию не добавляет константу. Однако добавление константы действительно желательно.

Чтобы добавить еще один столбец к вашей матрице, ck, заполненный единицами для представления константы, это будет константа уравнения пересечения. После этого ваши значения должны правильно совпасть.


Для тех, кто придет сюда в будущем (как я):

Этот код дает

[EDIT]

In response to a comment, I tried to use DataFrame as much as possible (numpy is required to invert a matrix).

The code gives


_TT_T

1,23817 silver badges23 bronze badges

3

In case you don't wanna deal with variance_inflation_factor and add_constant. Please consider the following two functions.

1. Use formula in statasmodels:


2. Use LinearRegression in sklearn:


Example:

answered Feb 24, 2019 at 23:06

stevensteven

2,32921 silver badges40 bronze badges

3

Хотя уже поздно, я вношу некоторые изменения в данном ответе. Чтобы получить лучший набор после удаления мультиколлинеарности, если мы используем решение @Chef1075, тогда мы потеряем переменные, которые коррелируют. Нам нужно удалить только одну из них. Для этого я пришел к следующему решению, используя ответ @steve:

answered Apr 26, 2020 at 13:36

asteroidasteroid

591 silver badge9 bronze badges

4

Example for Boston Data:

VIF (Коэффициент инфляции дисперсии) вычисляется с помощью вспомогательной регрессии, поэтому не зависит от фактического соответствия модели.

See below:

answered Aug 18, 2017 at 6:22

s_mjs_mj

54011 silver badges28 bronze badges

Я написал эту функцию, основываясь на некоторых других публикациях, которые видел на Stack Overflow и CrossValidated. Она отображает признаки, которые превышают порог, и возвращает новый DataFrame без этих признаков.

answered Jul 13, 2018 at 16:35

Chef1075Chef1075

2,6649 gold badges40 silver badges57 bronze badges

2

here code using dataframe python:

To create data

import numpy as np import scipy as sp

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

To create dataframe

import pandas as pd data = pd.DataFrame() data["a"] = a data["b"] = b data["c"] = c data["d"] = d

Calculate VIF

cc = np.corrcoef(data, rowvar=False) VIF = np.linalg.inv(cc) VIF.diagonal()

Result

array([22.95, 3. , 12.95, 3. ])

answered Jan 24, 2020 at 15:23

Еще одно решение. Следующий код дает точно такие же результаты VIF, как и пакет R car.

I've tested it on the titanic dataset. You can get the full example here: https://github.com/tulicsgabriel/Variance-Inflation-Factor-VIF-

answered Dec 1, 2021 at 23:00

b0zg0rb0zg0r

1051 silver badge7 bronze badges

Last updated