缺失值分析及处理
- 缺失值出现的原因分析
- 采取合适的方式对缺失值进行填充
异常值分析及处理
-
根据测试集数据的分布处理训练集的数据分布
-
使用合适的方法找出异常值
-
对异常值进行处理
深度清洗
- 分析每一个communityName、city、region、plate的数据分布并对其进行数据清洗
0、调包加载数据
首先,我们要做的就是加载可能要用到的包。以及源数据的导入;
#coding:utf-8
#导入warnings包,利用过滤器来实现忽略警告语句。
import warnings
warnings.filterwarnings('ignore')
# GBDT
from sklearn.ensemble import GradientBoostingRegressor
# XGBoost
import xgboost as xgb
# LightGBM
import lightgbm as lgb
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns #Seaborn其实是在matplotlib的基础上进行了更高级的API封装
from sklearn.model_selection import KFold #用于交叉验证的包
from sklearn.metrics import r2_score # 用于评价回归模型 的R²
from sklearn.preprocessing import LabelEncoder # 实现标签(Label) 标准化
import pickle #将对象以文件的形式存放在磁盘上,对一个 Python 对象结构的二进制序列化和反序列化
import multiprocessing #基于进程的并行
from sklearn.preprocessing import StandardScaler #数据预处理 去均值和方差归一化。且是针对每一个特征维度来做
ss = StandardScaler()
# k折交叉切分 用法类似Kfold,但是他是分层采样,确保训练集,测试集中各类别样本的比例与原始数据集中相同
from sklearn.model_selection import StratifiedKFold
# 从线性模型里导包
from sklearn.linear_model import ElasticNet, Lasso, BayesianRidge, LassoLarsIC,LinearRegression,LogisticRegression
# 机器学习里的包 不知道具体怎么用
from sklearn.pipeline import make_pipeline
from sklearn.preprocessing import RobustScaler
from sklearn.model_selection import train_test_split
from sklearn.ensemble import IsolationForest
# 导入数据:测试集 + 训练集
data_train = pd.read_csv("F:\\数据建模\\team-learning-master\\数据竞赛(房租预测)\\数据集\\train_data.csv")
data_test = pd.read_csv("F:\\数据建模\\team-learning-master\\数据竞赛(房租预测)\\数据集\\test_a.csv")
# 加辅助列
data_train['Type'] = 'Train'
data_test['Type'] = 'Test'
# 合并数据集
data_all = pd.concat([data_train, data_test], ignore_index=True) #纵向合并 横向用merge
data_all.head()
ID | Type | area | bankNum | buildYear | busStationNum | city | communityName | drugStoreNum | gymNum | ... | totalWorkers | tradeLandArea | tradeLandNum | tradeMeanPrice | tradeMoney | tradeNewMeanPrice | tradeNewNum | tradeSecNum | tradeTime | uv | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 100309852 | Train | 68.06 | 16 | 1953 | 36 | SH | XQ00051 | 12 | 15 | ... | 28248 | 0.0 | 0 | 47974.22551 | 2000.0 | 104573.48460 | 25 | 111 | 2018/11/28 | 284.0 |
1 | 100307942 | Train | 125.55 | 16 | 2007 | 184 | SH | XQ00130 | 27 | 5 | ... | 14823 | 0.0 | 0 | 40706.66775 | 2000.0 | 33807.53497 | 2 | 2 | 2018/12/16 | 22.0 |
2 | 100307764 | Train | 132.00 | 37 | 暂无信息 | 60 | SH | XQ00179 | 24 | 35 | ... | 77645 | 0.0 | 0 | 34384.35089 | 16000.0 | 109734.16040 | 11 | 555 | 2018/12/22 | 20.0 |
3 | 100306518 | Train | 57.00 | 47 | 暂无信息 | 364 | SH | XQ00313 | 83 | 30 | ... | 8750 | 108037.8 | 1 | 20529.55050 | 1600.0 | 30587.07058 | 58 | 260 | 2018/12/21 | 279.0 |
4 | 100305262 | Train | 129.00 | 10 | 暂无信息 | 141 | SH | XQ01257 | 21 | 5 | ... | 800 | 0.0 | 0 | 24386.36577 | 2900.0 | 51127.32846 | 34 | 38 | 2018/11/18 | 480.0 |
5 rows × 52 columns
1、缺失值处理
然后就是确实值得处理,先理清思路。什么是缺失值,已经在上篇文章中,阐述过了。这里按照实际情况处理缺失值;
主要思路分析
虽然这步骤是缺失值处理,但还会涉及到一些最最基础的数据处理。
- 缺失值处理
缺失值的处理手段大体可以分为:删除、填充、映射到高维(当做类别处理)。
根据任务一,直接找到的缺失值情况是pu和pv;但是,根据特征nunique分布的分析,可以发现rentType存在"–“的情况,这也算是一种缺失值。
此外,诸如rentType的"未知方式”;houseToward的"暂无数据"等,本质上也算是一种缺失值,但是对于这些缺失方式,我们可以把它当做是特殊的一类处理,而不需要去主动修改或填充值。
将rentType的"–“转换成"未知方式"类别;
pv/pu的缺失值用均值填充;
buildYear存在"暂无信息”,将其用众数填充。
-
转换object类型数据
这里直接采用LabelEncoder的方式编码,详细的编码方式请自行查阅相关资料学习。 -
时间字段的处理
buildYear由于存在"暂无信息",所以需要主动将其转换int类型;
tradeTime,将其分割成月和日。 -
删除无关字段
ID是唯一码,建模无用,所以直接删除;
city只有一个SH值,也直接删除;
tradeTime已经分割成月和日,删除原来字段
def preprocessingData(data):
# 填充缺失值
data['rentType'][data['rentType'] == '--'] = '未知方式' # 把rentType列 里 "--" 的值填充为 "未知方式"
# 转换object类型数据
columns = ['rentType','communityName','houseType', 'houseFloor', 'houseToward', 'houseDecoration', 'region', 'plate']
for feature in columns:
data[feature] = LabelEncoder().fit_transform(data[feature])
# LabelEncoder() 调用处理标签的包 对数据进行标准化,降维,归一化等操作(比如标准化~N(0,1)
# 将buildYear列转换为整型数据
buildYearmean = pd.DataFrame(data[data['buildYear'] != '暂无信息']['buildYear'].mode()) # mode() 众数函数
# 找出buildYear 列 值不等于"暂无信息" 的值得集合 中的众数
data.loc[data[data['buildYear'] == '暂无信息'].index, 'buildYear'] = buildYearmean.iloc[0, 0] # 用众数填补 暂无信息 的值
# loc:通过选取行(列)标签索引数据
# iloc:通过选取行(列)位置编号索引数据
# ix:既可以通过行(列)标签索引数据,也可以通过行(列)位置编号索引数据
data['buildYear'] = data['buildYear'].astype('int')# 将变量buildYear转换为int型
# 处理pv和uv的空值
data['pv'].fillna(data['pv'].mean(), inplace=True) # 均值填充缺失值
data['uv'].fillna(data['uv'].mean(), inplace=True) # 同上
data['pv'] = data['pv'].astype('int') # 将变量 转换为int型
data['uv'] = data['uv'].astype('int')
# 分割交易时间
def month(x):
month = int(x.split('/')[1]) # split() 通过指定分隔符对字符串进行切片
return month
def day(x):
day = int(x.split('/')[2])
return day
data['month'] = data['tradeTime'].apply(lambda x: month(x)) # 根据month()函数 切割tradeTime
data['day'] = data['tradeTime'].apply(lambda x: day(x)) # 根据day()函数 切割tradeTime
# 去掉部分特征
data.drop('city', axis=1, inplace=True) #drop函数默认删除行,列需要加axis = 1
data.drop('tradeTime', axis=1, inplace