具有字符串/分类特征(变量)的线性回归分析?

回归算法似乎正在处理以数字表示的特征。 例如:

simple data without categorical features

这个数据集不包含分类特征/变量。很清楚如何对这些数据进行回归和预测价格。


但是现在我想做一个关于数据的回归分析,这些数据包含了分类特征:

data-set with categorical features

5的特点: DistrictConditionMaterialSecurityType


如何对这些数据进行回归?是否需要手动将所有字符串/分类数据转换为数字?我的意思是,如果我必须创建一些编码规则,并根据这些规则将所有数据转换为数值。

有没有什么简单的方法可以将字符串数据转换为数字,而不必手动创建我自己的编码规则?也许 巨蟒中有一些库可以用来实现这一点?是否存在由于“错误编码”导致回归模型不正确的风险?

122691 次浏览

在这种情况下,您可以使用“虚拟编码”。 有一些 Python 库可以进行虚拟编码,您可以选择以下几种方式:

  • 您可以使用 scikit-learn库。
  • 或者,如果您使用的是 pandas,它有一个内置的 创建虚拟变量函数。

熊猫的例子如下:

import pandas as pd


sample_data = [[1,2,'a'],[3,4,'b'],[5,6,'c'],[7,8,'b']]
df = pd.DataFrame(sample_data, columns=['numeric1','numeric2','categorical'])
dummies = pd.get_dummies(df.categorical)
df.join(dummies)

是的,你必须把所有的东西都转换成数字,这需要考虑这些属性代表什么。

通常有三种可能性:

  1. 分类数据的单热编码
  2. 有序数据的任意数字
  3. 对分类数据使用类似分组的方法(例如城市地区的平均价格)。

你必须小心,不要注入信息,你没有在申请的情况下。

一个热编码

如果您有分类数据,您可以为每个可能的值创建具有0/1值的虚拟变量。

例如。

idx color
0   blue
1   green
2   green
3   red

idx blue green red
0   1    0     0
1   0    1     0
2   0    1     0
3   0    0     1

这对熊猫来说很容易做到:

import pandas as pd


data = pd.DataFrame({'color': ['blue', 'green', 'green', 'red']})
print(pd.get_dummies(data))

会导致:

   color_blue  color_green  color_red
0           1            0          0
1           0            1          0
2           0            1          0
3           0            0          1

有序数据的数字

创建可分类类别的映射,例如。 旧 < 翻新 < 新→0,1,2

对于大熊猫来说,这也是可能的:

data = pd.DataFrame({'q': ['old', 'new', 'new', 'ren']})
data['q'] = data['q'].astype('category')
data['q'] = data['q'].cat.reorder_categories(['old', 'ren', 'new'], ordered=True)
data['q'] = data['q'].cat.codes
print(data['q'])

结果:

0    0
1    2
2    2
3    1
Name: q, dtype: int8

为 groupby 操作使用分类数据

您可以使用过去(已知事件)的每个类别的平均值。

假设你有一个数据框架,其中包含城市最新已知的平均价格:

prices = pd.DataFrame({
'city': ['A', 'A', 'A', 'B', 'B', 'C'],
'price': [1, 1, 1, 2, 2, 3],
})
mean_price = prices.groupby('city').mean()
data = pd.DataFrame({'city': ['A', 'B', 'C', 'A', 'B', 'A']})


print(data.merge(mean_price, on='city', how='left'))

结果:

  city  price
0    A      1
1    B      2
2    C      3
3    A      1
4    B      2
5    A      1

在使用分类变量的线性回归中,你应该小心虚拟变量陷阱。虚拟变量陷阱是一种自变量是多重共线的情况——一种两个或多个变量高度相关的情况; 简单地说,一个变量可以从其他变量中预测出来。这会产生模型的奇异性,这意味着你的模型就是不能工作。点击这里阅读

想法是使用虚拟变量编码与 drop_first=True,这将省略一列从每个类别转换分类变量到虚拟/指示器变量。你的 不会的丢失了任何相关的信息,仅仅是因为你在数据集中的所有点都可以通过其他的特性来完全解释。

这里是完整的代码如何可以做到这一点,为您的住房数据集

所以你有分类特征:

District, Condition, Material, Security, Type

还有一个你们试图预测的数字特征:

Price

首先,你需要分割你的初始数据集的输入变量和预测,假设它的熊猫数据框架看起来像这样:

输入变量:

X = housing[['District','Condition','Material','Security','Type']]

预测:

Y = housing['Price']

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

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

所以现在如果你用 drop_first=True检查 X 的形状,你会看到它少了4列-每列对应一个分类变量。

您现在可以继续在线性模型中使用它们:

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)

使用分类变量作为独立变量实现回归的一种方法如上所述——使用编码。 另一种方法是使用 statmodel 库使用类似 R 的统计公式。下面是一个代码片段

from statsmodels.formula.api import ols
tips = sns.load_dataset("tips")


model = ols('tip ~ total_bill + C(sex) + C(day) + C(day) + size', data=tips)
fitted_model = model.fit()
fitted_model.summary()

数据集

total_bill  tip     sex  smoker day  time  size
0   16.99   1.01    Female  No  Sun Dinner  2
1   10.34   1.66    Male    No  Sun Dinner  3
2   21.01   3.50    Male    No  Sun Dinner  3
3   23.68   3.31    Male    No  Sun Dinner  2
4   24.59   3.61    Female  No  Sun Dinner  4

回归概述

enter image description here