PS:这个eda主要是抄的kaggle上的一个share,我在他的baseline基础上增加了我的内容。为啥我不自己做呢?因为初始特征就有81个,我懒啊。。。。。。另外eda的思想差不多,他的idea和我的idea差不多,一个个的赋值特征名称实在是太烦人了。
import numpy as np
import pandas as pd
from sklearn.preprocessing import LabelEncoder
import matplotlib.pyplot as plt
from scipy.special import boxcox1p
import seaborn as sns
import warnings
def ignore_warn(*args, **kwargs):
pass
warnings.warn = ignore_warn #ignore annoying warning (from sklearn and seaborn)
from scipy import stats
from scipy.stats import norm, skew #for some statistics
%matplotlib inline
数据读取
train_data = pd.read_csv('C:/ml_data/house/naive/train.csv')
test_data = pd.read_csv('C:/ml_data/house/naive/test.csv')
特征理解
1.特征含义:共有81个特征,您牛逼 共有1460个样本
1.MSSubClass :建筑的类别 类别特征
2.MSZoning: 建筑的地区 类别特征
3.LotFrontage: 与最近的街道的距离 数值特征
4.LotArea:地块面积 数值特征
5.Street:房子路的类别 类别特征
6.Alley:房子小道的类别 类别特诊
7.LotShape:房子形状是否OK 类别特征
8.LandContour:房子地形平整度 类别特诊
9.Utilities:可用资源 类别特征
10.LotConfig:Lot的配置 类别特征
11.LandSlope: 土地斜坡 类别特征
12.Neighborhood:市区位置 类别特征
13.Condition1: 位置特性 类别特征
14.Condition2:位置特性 类别特征
15.BldgType:住宅类型 类别特征
16.HouseStyle:住宅风格 类别特征
17.OverallQual:房子的装修质量 类别特征
18.OverallCond:房子的状态质量等级 类别特征
19.YearBuilt:盖房子的时间 数值特征
20.YearRemodAdd:改造时间 数值特征
21.RoofStyle:房顶类型 类别特征
22.RoofMatl:房顶材料 类别特征
23.Exterior1st:房顶外部覆盖物 类别特征
24.Exterior2nd:房顶外部覆盖物 类别特征
25.MasVnrType:砖石饰面类型 类别特征
26.MasVnrArea:砖石饰面面积 数值特征
27.ExterQual: 外部材料的质量 类别特征
28.ExterCond: 外部材料的现状 类别特征
29.Foundation: 地基类型 类别特征
30.BsmtQual: 评估地下室高度 类别特征
31.BsmtCond:评估地下室现状 类别特征
32.BsmtExposure: 室外花园墙现状 类别特征
33.BsmtFinType1:地下室已完成评分 类别特征
34.BsmtFinSF1:地下室已完成面积 数值特征
35.BsmtFinType2:地下室已完成评分 类别特征
36.BsmtFinSF2:地下室已完成面积 数值特征
37.BsmtUnfSF: 地下室未完成面积 数值特征
38.TotalBsmtSF:地下室总面积 数值特征
39.Heating: 热来源类别 类别特征
40.HeatingQC: 热来源质量 类别特征
41.CentralAir:中央空调 类别特征
42.Electrical: 电力系统 类别特征
43.stFlrSF: 一楼面积 数值特征
44.2ndFlrSF: : 二楼面积 数值特征
45.LowQualFinSF:低质量面积 数值特征
46.GrLivArea:地上面积 数值特征
47.BsmtFullBath: 地下室全浴室 类别特征
48.BsmtHalfBath: 地下室半浴室 类别特征
49.FullBath: 地上全浴室 类别特征
50.HalfBath: 地上半浴室 类别特征
51:BedroomAbvGr:卧室在地上几层? 类别特征
52.Kitchen: 厨房在地上? 类别特征
53.KitchenQual: 厨房质量 类别特征
54.TotRmsAbvGrd: 地上房间总数量 类别特征
55.Functional: 家庭功能 类别特征
56.Fireplaces: Fireplaces: 数量 类别特征
57.FireplaceQu: Fireplaces 类别特征
58.GarageType: Garage类型 类别特征
59.GarageYrBlt: garage建造时间 数值特征
60.GarageFinish: 完成度 类别特征
61.GarageCars: 能放几辆车 类别特征
62.GarageArea: 车库面积 数值特征
63.GarageQual: 车库质量 类别特征
64.GarageCond: 车库现状 类别特征
65.PavedDrive: 铺面路道 类别特征
66.WoodDeckSF: 木夹板面积 数值特征
67.OpenPorchSF: 门廊面积 数值特征
68.EnclosedPorch: 内门廊面积 数值特征
69.3SsnPorch: 3S面积 数值特征
70.ScreenPorch: 屏幕门廊面积 数值特征
71.PoolArea: 泳池面积 数值特征
72.PoolQC: 泳池质量 类别特征
73.Fence: 围栏质量 类别特征
74.Miscellaneous feature:杂项功能 类别特征
75.MiscVal: 杂项价值 数值特征
76.MoSold: 出售的月份 类别特征
77.YrSold: 出售的年 类别特征
78.SaleType: 销售的形式 类别特征
79.SaleCondition: 销售的状态 类别特征
80.SalePrice:销售价格 类别特征
2.特征类别:
1.类别特征:
2.数值特征: [‘LotFrontage’,‘LotArea’,‘YearBuilt’,‘YearRemodAdd’,‘MasVnrArea’,‘BsmtFinSF1’,‘BsmtFinSF2’,‘BsmtUnfSF’,‘TotalBsmtSF’,‘1stFlrSF’,‘2ndFlrSF’,‘LowQualFinSF’,‘GrLivArea’,‘GarageArea’,‘WoodDeckSF’,‘OpenPorchSF’,‘EnclosedPorch’,‘3SsnPorch’,‘ScreenPorch’,‘PoolArea’,‘MiscVal’]
3.target :
‘SalePrice’
train_data.drop('Id',inplace = True ,axis = 1)
test_data.drop('Id',inplace = True ,axis = 1)
异常值处理
本例中异常值判断主要靠人工
numric_fea = ['LotFrontage','LotArea','YearBuilt','YearRemodAdd','MasVnrArea','BsmtFinSF1','BsmtFinSF2','BsmtUnfSF','TotalBsmtSF','1stFlrSF','2ndFlrSF','LowQualFinSF','GrLivArea','GarageArea','WoodDeckSF','OpenPorchSF','EnclosedPorch','3SsnPorch','ScreenPorch','PoolArea','MiscVal']
fig, ax = plt.subplots()
ax.scatter(x = train_data[numric_fea[0]],y = train_data['SalePrice'])
plt.show()
最右边的两个点可以视为离群点,直接删除这一行数据。(也可以填充)
train_data = train_data.drop(train_data[(train_data[numric_fea[0]] > 300)].index)
删除之后,可视化一下。
这种异常值判定是玄学,很难说点值是不是异常值。
train_data = train_data.drop(train_data[(train_data[numric_fea[0]] > 300)].index)
target正态化分析
print(train_data['SalePrice'].skew(),train_data['SalePrice'].kurt())
1.8828757597682129 6.536281860064529
偏度1.88,进行np.log1p处理
train_data['SalePrice'] = np.log1p(train_data['SalePrice'])
print(train_data['SalePrice'].skew(),train_data['SalePrice'].kurt())
0.12134661989685333 0.809519155707878
偏度和峰度都降低了很多
缺失值处理
train_y = train_data.SalePrice.values
train_data.drop(['SalePrice'],inplace = True,axis = 1)
all_data = pd.concat((train_data,test_data)).reset_index(drop = True)
all_data_miss = all_data.isnull().sum()/len(all_data) * 100
all_data_miss = all_data_miss.drop(all_data_miss[all_data_miss == 0].index).sort_values(ascending = False)
all_data_miss = pd.DataFrame({'Missing Ratio' :all_data_miss})
可以看到top5的缺失值比例比姚明还高,正常来这么高的比例特征是应该直接删除的。但是top5都是类别型特征,可以使用新的特征值进行填充。
所有的缺失值填充的代码
all_data["PoolQC"] = all_data["PoolQC"].fillna("None")
all_data["MiscFeature"] = all_data["MiscFeature"].fillna("None")
all_data["Alley"] = all_data["Alley"].fillna("None")
all_data["Fence"] = all_data["Fence"].fillna("None")
all_data["FireplaceQu"] = all_data["FireplaceQu"].fillna("None")
all_data["LotFrontage"] = all_data.groupby("Neighborhood")["LotFrontage"].transform(lambda x: x.fillna(x.median()))
for col in ('GarageType', 'GarageFinish', 'GarageQual', 'GarageCond'):
all_data[col] = all_data[col].fillna('None')
for col in ('GarageYrBlt', 'GarageArea', 'GarageCars'):
all_data[col] = all_data[col].fillna(0)
for col in ('BsmtFinSF1', 'BsmtFinSF2', 'BsmtUnfSF','TotalBsmtSF', 'BsmtFullBath', 'BsmtHalfBath'):
all_data[col] = all_data[col].fillna(0)
for col in ('BsmtQual', 'BsmtCond', 'BsmtExposure', 'BsmtFinType1', 'BsmtFinType2'):
all_data[col] = all_data[col].fillna('None')
all_data["MasVnrType"] = all_data["MasVnrType"].fillna("None")
all_data["MasVnrArea"] = all_data["MasVnrArea"].fillna(0)
all_data['MSZoning'] = all_data['MSZoning'].fillna(all_data['MSZoning'].mode()[0])
all_data = all_data.drop(['Utilities'], axis=1)
all_data["Functional"] = all_data["Functional"].fillna("Typ")
all_data['Electrical'] = all_data['Electrical'].fillna(all_data['Electrical'].mode()[0])
all_data['KitchenQual'] = all_data['KitchenQual'].fillna(all_data['KitchenQual'].mode()[0])
all_data['Exterior1st'] = all_data['Exterior1st'].fillna(all_data['Exterior1st'].mode()[0])
all_data['Exterior2nd'] = all_data['Exterior2nd'].fillna(all_data['Exterior2nd'].mode()[0])
all_data['SaleType'] = all_data['SaleType'].fillna(all_data['SaleType'].mode()[0])
all_data['MSSubClass'] = all_data['MSSubClass'].fillna("None")
特征改造
#MSSubClass=The building class
all_data['MSSubClass'] = all_data['MSSubClass'].apply(str)
#Changing OverallCond into a categorical variable
all_data['OverallCond'] = all_data['OverallCond'].astype(str)
#Year and month sold are transformed into categorical features.
all_data['YrSold'] = all_data['YrSold'].astype(str)
all_data['MoSold'] = all_data['MoSold'].astype(str)
all_data['TotalSF'] = all_data['TotalBsmtSF'] + all_data['1stFlrSF'] + all_data['2ndFlrSF']
类别型特征进行序号编码
cols = ('FireplaceQu', 'BsmtQual', 'BsmtCond', 'GarageQual', 'GarageCond',
'ExterQual', 'ExterCond','HeatingQC', 'PoolQC', 'KitchenQual', 'BsmtFinType1',
'BsmtFinType2', 'Functional', 'Fence', 'BsmtExposure', 'GarageFinish', 'LandSlope',
'LotShape', 'PavedDrive', 'Street', 'Alley', 'CentralAir', 'MSSubClass', 'OverallCond',
'YrSold', 'MoSold')
# process columns, apply LabelEncoder to categorical features
for c in cols:
lbl = LabelEncoder()
lbl.fit(list(all_data[c].values))
all_data[c] = lbl.transform(list(all_data[c].values))
数值型特征进行正态化处理
numeric_feats = all_data.dtypes[all_data.dtypes != "object"].index
skewed_feats = all_data[numeric_feats].apply(lambda x: skew(x.dropna())).sort_values(ascending=False)
skewness = pd.DataFrame({'Skew' :skewed_feats})
skewness_abs = skewness[abs(skewness) > 0.75]
skewed_features = skewness_abs.index
lam = 0.15
for feat in skewed_features:
#all_data[feat] += 1
all_data[feat] = boxcox1p(all_data[feat], lam)
转化成哑变量
all_data_dummy = pd.get_dummies(all_data)
保存数据
all_data_dummy.to_csv('C:/ml_data/house/all_data_dummy.csv')
ntrain = train_data.shape[0]
ntest = test_data.shape[0]
train_data = all_data_dummy[0:ntrain]
test_data = all_data_dummy[ntrain:]
train_data['train_y'] = train_y
train_data.to_csv('C:/ml_data/house/train_data_dummy.csv')
test_data.to_csv('C:/ml_data/house/test_data_dummy.csv')