数据预处理的一些操作(一)

做了个房价预测的模型,其中数据预处理部分占了很多工作量,说一下其任务流程:

(一):分析数据指标

  • 不同指标对结果的影响
    *特征相关性

  • 连续值与离散值的情况
    *boxplot

(二):观察数据正太性(符合大部分人群的指标)
如地皮面积很大,价格却很低,这是比较偏离普遍性的情况,通过观察正太分布分析数据

  • 是否满足正太分布
    *偏度
    *QQ图
    *正太分布图

  • 数据倾斜的处理
    *样本正太分布变换(log变换)
    *boxcox

(三):数据预处理

  • 缺失值填充
    *中数、众数填充的选择
  • 标签转换 LabelEncoder()

(四):集成方法建模对比

  • 单模型回归效果
  • 平均与堆叠效果对比

1、首先查看数据,有很多特征,salaprice为要预测的结果

在这里插入图片描述

2、离散型变量,用boxplot表示

由于现实数据中总是存在各式各样地“脏数据”,也成为“离群点”,于是为了不因这些少数的离群数据导致整体特征的偏移,将这些离群点单独汇出,而盒图中的胡须的两级修改成最小观测值与最大观测值。这里有个经验,就是最大(最小)观测值设置为与四分位数值间距离为1.5个IQR(中间四分位数极差)。

扫描二维码关注公众号,回复: 6178462 查看本文章
  • 即IQR = Q3-Q1,即上四分位数与下四分位数之间的差,也就是盒子的长度。
    在这里插入图片描述

  • 最小观测值为min = Q1 - 1.5*IQR,如果存在离群点小于最小观测值,则胡须下限为最小观测值,离群点单独以点汇出。如果没有比最小观测值小的数,则胡须下限为最小值。

  • 最大观测值为max = Q3 -1.5*IQR,如果存在离群点大于最大观测值,则胡须上限为最大观测值,离群点单独以点汇出。如果没有比最大观测值大的数,则胡须上限为最大值

偏度:

  • 对称分布:中位线在箱子中间,上下相邻值到箱子的距离等长,离群点在上下限值外的分布也大致相同。
  • 右偏分布:中位数更靠近下四分位数,上相邻值到箱子的距离比下相邻值到箱子的距离长,离群点多数在上限值之外。
  • 左偏分布:中位数更靠近上四分位数,下相邻值到箱子的距离比上相邻值到箱子的距离长,离群点多数在下限值之外。
    在这里插入图片描述
#整体材料和饰面质量
var = 'OverallQual'
data = pd.concat([df_train['SalePrice'], df_train[var]], axis=1)
f, ax = plt.subplots(figsize=(8, 6))
fig = sns.boxplot(x=var, y="SalePrice", data=data)
fig.axis(ymin=0, ymax=800000);

在这里插入图片描述

3、特征之间的相关性

#df_train为dataframe数据
corrmat = df_train.corr()
f, ax = plt.subplots(figsize=(12, 9))
sns.heatmap(corrmat, square=True,cmap='YlGnBu');

当特征很多时,可以只提取相关性较大的前几个特征展示

  • heatmap():画热度图时候,参数很多,但只需要最重要的data即下面的cm即可
  • corrcoef():该函数得到相关系数矩阵
k = 10 #number of variables for heatmap
cols = corrmat.nlargest(k, 'SalePrice')['SalePrice'].index

cm = np.corrcoef(df_train[cols].values.T) 
sns.set(font_scale=1.25)
hm = sns.heatmap(cm, cbar=True, annot=True, square=True, fmt='.2f', annot_kws={'size': 10}, yticklabels=cols.values, xticklabels=cols.values,cmap='YlGnBu')
plt.show()

在这里插入图片描述

4、缺失值

缺失值一般填充与特征有关系的值

  • 众数(对于一些普遍性的指标,用众数填充即可) df.mode() 返回出现频率最高的数值
  • 中位数

得到缺失值的总数和占比

total = df_train.isnull().sum().sort_values(ascending=False)
percent = (df_train.isnull().sum()/df_train.isnull().count()).sort_values(ascending=False)
missing_data = pd.concat([total, percent], axis=1, keys=['Total', 'Percent'])
missing_data.head(20)

在这里插入图片描述

  • fillna()会填充nan数据,返回填充后的结果。如果希望在原DataFrame中修改,则把inplace设置为True
 all_data[col] = all_data[col].fillna(0)
 all_data[col] = all_data[col].fillna('None')

5、离群点的处理

  • 直接drop去掉即可
train = train.drop(train[(train['GrLivArea']>4000) & (train['SalePrice']<300000)].index)

#Check the graphic again
fig, ax = plt.subplots()
ax.scatter(train['GrLivArea'], train['SalePrice'])
plt.ylabel('SalePrice', fontsize=13)
plt.xlabel('GrLivArea', fontsize=13)
plt.show()

6、数据倾斜处理:样本正太分布变换

  • 保持单调性:如x随着y增大,不能变换之后x随着y变小
  • 对于有较大偏度的特征,改善总体分布的正态性(尾巴:数据倾斜) 措施:对数变换
    如下图的ln(y),数据较小的时候,变化较大,数据较大的时候,对其进行平滑,而不会这么分散,即可改善数据倾斜
    在这里插入图片描述

查看特征的正太分布和偏度:

import seaborn as sns
sns.distplot(df_train['SalePrice']);

#skewness and kurtosis
print("Skewness: %f" % df_train['SalePrice'].skew())
print("Kurtosis: %f" % df_train['SalePrice'].kurt())

发现数据有些倾斜:(正太分布应是左右对称的)
在这里插入图片描述
在这里插入图片描述

  • 正太分布图
  • QQ图:数据若符合正太分布,则会为一条直线,偏离则不符合
sns.distplot(train['SalePrice'] , fit=norm);

(mu, sigma) = norm.fit(train['SalePrice'])
print( '\n mu = {:.2f} and sigma = {:.2f}\n'.format(mu, sigma))

#分布图  将算得的均值、标准差传入正太分布图中
plt.legend(['Normal dist. ($\mu=$ {:.2f} and $\sigma=$ {:.2f} )'.format(mu, sigma)],
            loc='best')
plt.ylabel('Frequency')
plt.title('SalePrice distribution')

#QQ图  数据若符合正太分布,则会为一条直线,偏离则不符合
fig = plt.figure()
res = stats.probplot(train['SalePrice'], plot=plt)
plt.show()

在这里插入图片描述
变换:

#对数变换log(1+x)
train["SalePrice"] = np.log1p(train["SalePrice"])

#看看新的分布
sns.distplot(train['SalePrice'] , fit=norm);

# 参数
(mu, sigma) = norm.fit(train['SalePrice'])
print( '\n mu = {:.2f} and sigma = {:.2f}\n'.format(mu, sigma))

#画图
plt.legend(['Normal dist. ($\mu=$ {:.2f} and $\sigma=$ {:.2f} )'.format(mu, sigma)],
            loc='best')
plt.ylabel('Frequency')
plt.title('SalePrice distribution')

在这里插入图片描述

7、对特征偏度较大的进行变换-Box-Cox

Box-Cox:找到一个合适的函数使得数据点经过变换之后能整体的正太型能够最好

在这里插入图片描述

关键点在于如何找到一个合适的参数,一般情况下0.15为经验值
偏度的计算:

from scipy.stats import norm, skew

numeric_feats = all_data.dtypes[all_data.dtypes != "object"].index

# Check the skew of all numerical features
skewed_feats = all_data[numeric_feats].apply(lambda x: skew(x.dropna())).sort_values(ascending=False)
print("\nSkew in numerical features: \n")
skewness = pd.DataFrame({'Skew' :skewed_feats})
skewness.head(10)

变换:

skewness = skewness[abs(skewness) > 0.75]
print("There are {} skewed numerical features to Box Cox transform".format(skewness.shape[0]))

from scipy.special import boxcox1p
skewed_features = skewness.index
lam = 0.15
for feat in skewed_features:
    all_data[feat] = boxcox1p(all_data[feat], lam)

猜你喜欢

转载自blog.csdn.net/qq_38016957/article/details/89608151
今日推荐