使用虚拟/分类变量的线性回归

19

我有一组数据。我已经使用pandas将它们分别转换为虚拟变量和分类变量。现在,我想知道如何在Python中运行多元线性回归(我正在使用statsmodels)。是否有一些考虑因素或者我必须在代码中指出这些变量是虚拟/分类变量?或者,变量的转换已足够,我只需要运行回归模型model = sm.OLS(y, X).fit()即可?

我的代码如下:

datos = pd.read_csv("datos_2.csv")
df = pd.DataFrame(datos)
print(df)

我得到了这个:

Age  Gender    Wage         Job         Classification 
32    Male  450000       Professor           High
28    Male  500000  Administrative           High
40  Female   20000       Professor            Low
47    Male   70000       Assistant         Medium
50  Female  345000       Professor         Medium
27  Female  156000       Assistant            Low
56    Male  432000  Administrative            Low
43  Female  100000  Administrative            Low

然后我这样做:1表示男性,0表示女性;1表示教授,2表示管理人员,3表示助理。

df['Sex_male']=df.Gender.map({'Female':0,'Male':1})
        df['Job_index']=df.Job.map({'Professor':1,'Administrative':2,'Assistant':3})
print(df)

获得这个:

 Age  Gender    Wage             Job Classification  Sex_male  Job_index
 32    Male  450000       Professor           High         1          1
 28    Male  500000  Administrative           High         1          2
 40  Female   20000       Professor            Low         0          1
 47    Male   70000       Assistant         Medium         1          3
 50  Female  345000       Professor         Medium         0          1
 27  Female  156000       Assistant            Low         0          3
 56    Male  432000  Administrative            Low         1          2
 43  Female  100000  Administrative            Low         0          2

现在,如果我要运行一个多元线性回归模型,例如:

y = datos['Wage']
X = datos[['Sex_mal', 'Job_index','Age']]
X = sm.add_constant(X)
model1 = sm.OLS(y, X).fit()
results1=model1.summary(alpha=0.05)
print(results1)

结果通常会显示,但这样可以吗?还是我需要以某种方式指示变量是虚拟的或分类的?请帮忙,我是Python新手,我想学习。来自南美洲-智利的问候。

2个回答

26
您需要指示JobJob_index是分类变量;否则,在Job_index的情况下,它将被视为连续变量(其值恰好为123),这是不正确的。在statsmodels中,您可以使用几种不同的符号表示法,以下是使用公式方法的示例,其中使用C()表示分类变量:
from statsmodels.formula.api import ols

fit = ols('Wage ~ C(Sex_male) + C(Job) + Age', data=df).fit() 

fit.summary()

                            OLS Regression Results                            
==============================================================================
Dep. Variable:                   Wage   R-squared:                       0.592
Model:                            OLS   Adj. R-squared:                  0.048
Method:                 Least Squares   F-statistic:                     1.089
Date:                Wed, 06 Jun 2018   Prob (F-statistic):              0.492
Time:                        22:35:43   Log-Likelihood:                -104.59
No. Observations:                   8   AIC:                             219.2
Df Residuals:                       3   BIC:                             219.6
Df Model:                           4                                         
Covariance Type:            nonrobust                                         
=======================================================================================
                          coef    std err          t      P>|t|      [0.025      0.975]
---------------------------------------------------------------------------------------
Intercept             3.67e+05   3.22e+05      1.141      0.337   -6.57e+05    1.39e+06
C(Sex_male)[T.1]     2.083e+05   1.39e+05      1.498      0.231   -2.34e+05    6.51e+05
C(Job)[T.Assistant] -2.167e+05   1.77e+05     -1.223      0.309    -7.8e+05    3.47e+05
C(Job)[T.Professor] -9273.0556   1.61e+05     -0.058      0.958   -5.21e+05    5.03e+05
Age                 -3823.7419   6850.345     -0.558      0.616   -2.56e+04     1.8e+04
==============================================================================
Omnibus:                        0.479   Durbin-Watson:                   1.620
Prob(Omnibus):                  0.787   Jarque-Bera (JB):                0.464
Skew:                          -0.108   Prob(JB):                        0.793
Kurtosis:                       1.839   Cond. No.                         215.
==============================================================================

注意: JobJob_index 不会使用相同的分类级别作为基准线,因此您将在每个级别的虚拟系数中看到略微不同的结果,尽管整体模型适合度保持不变。

好的,非常感谢,但是出现了一个新的问题,因为在结果中只显示了“性别——男性”这一系数,而没有显示另一类别(男性和女性)的系数?同样地,在工作方面,也仅显示了三个类别中的两个的系数? 你能解释一下为什么会发生这种情况吗? - Héctor Alonso
在回归中,任何分类变量都需要使用一个基准水平来比较其他水平。这样你就可以得到每个类别水平的单独系数 - 系数将指示该水平的预测信号,与基线相比。基线不会与自身进行比较,因此没有系数。您可以查看对比信息以获取更多信息(但有关此问题的进一步问题更适合于CrossValidated而不是StackOverflow)。 - andrew_reece
@Héctor Alonso 如果这个答案解决了你的问题,请点击答案旁边的勾号标志将其标记为已接受。谢谢! - andrew_reece
1
完成。谢谢:D 非常有帮助。 - Héctor Alonso
由于某些原因,这个解决方案对我不起作用 :/ 我已经在这里发布了我的问题:https://dev59.com/q3gPtIcB2Jgan1znb7mL - guin0x

19
在使用分类变量进行线性回归时,您应该注意虚拟变量陷阱。虚拟变量陷阱是指独立变量多重共线性的情况——两个或更多变量高度相关的情况;简单来说,一个变量可以从其他变量中预测出来。这可能会导致模型的奇异性,意味着您的模型将无法工作。在此处阅读更多信息 思路是使用虚拟变量编码,并设置drop_first=True,这将在将分类变量转换为虚拟/指示变量后省略每个类别中的一列。这样做不会丢失任何相关信息,因为数据集中的所有点都可以通过其余特征完全解释。
以下是如何针对作业数据集完成代码的完整代码
所以你有你的X特征:
Age, Gender, Job, Classification 

同时,你要预测的一个数值特征是:

Wage

首先,您需要根据输入变量和预测将初始数据集拆分,假设它是pandas dataframe,它看起来像这样:

输入变量(您的数据集可能有所不同,但整个代码保持不变,您将把数据集中的每一列放在X中,除了一个将进入Y。pd.get_dummies可以毫不费力地处理这样的情况- 它只会转换分类变量,而不会触及数值):

X = jobs[['Age','Gender','Job','Classification']]

预测:

Y = jobs['Wage']

将分类变量转换为虚拟/指示变量,并在每个类别中删除一个:

X = pd.get_dummies(data=X, drop_first=True)

现在,如果您使用 drop_first=True 检查 X 的形状(X.shape),您将看到它少了 4 列 - 每个分类变量少一列。

现在,您可以继续在线性模型中使用它们。对于 scikit-learn 实现,它可能如下所示:

from sklearn import linear_model
from sklearn.model_selection import train_test_split
    
X_train, X_test, Y_train, Y_test = train_test_split(X, Y, test_size = .20, random_state = 40)
    
regr = linear_model.LinearRegression() # Do not use fit_intercept = False if you have removed 1 column after dummy encoding
regr.fit(X_train, Y_train)
predicted = regr.predict(X_test)

你好!如何绘制这些值?我的显示X和y值的大小不同。 - Noob Programmer
1
非常简洁的描述!谢谢! - undefined

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接