Datawhale房租预测实战学习笔记(数据清洗)
缺失值处理
缺失值的处理方法这篇文章总结得比较全面:缺失值处理方法综述
总的来说可以分为三大方法:(1)删除;(2)填补;(3)不处理。对于这种多特征的回归模型,我认为不处理缺失值会对往模型里输入数据造成问题,故应采取前两种方法。
根据上一次的分析,51个特征列中,pv和uv两列含有18个null值,初步猜想这18个null值出现在相同样本中,下面用代码进行验证:
pv_nullindex = list(data[data.pv.isnull()].index) # 得到 pv列 null值索引
uv_nullindex = list(data[data.uv.isnull()].index) # 得到 uv列 null值索引
print(pv_nullindex==uv_nullindex) # 判断索引是否一致
#结果
True
pv字段内容是:该板块当月租客浏览网页次数;uv字段内容是:该板块当月租客浏览网页总人数;参考分析在这里分别用均值对pv和uv进行插值,我认为18个缺失值对于41440个样本来说,直接删除这18个样本可能要比随便插进去一个值要来得好一点,不过严谨一点的话应该绘制pv和uv的分布图来看一下再做决定。
%matplotlib inline
import seaborn as sns
import matplotlib.pyplot as plt
plt.rcParams['axes.unicode_minus'] = False
sns.distplot(data['pv'].dropna()) # 这里注意一定要先drop掉null值才可以画图
sns.distplot(data['uv'].dropna()) # 直方图中纵坐标表示对应区间的区间的概率密度,面积和为1
从pv和uv的分布图可以明显看出用均值去插值是没什么道理的,因为大部分样本都集中在左边。故接下来绘图观察pv、uv是否与tradeMoney(Label)存在关系,若存在关系即可插值,若明显不存在关系则选择直接删除这18个样本。
data = data.dropna()
sns.jointplot(x=data[data['pv'] < 200000]['pv'], y=data[data['pv'] < 200000]['tradeMoney'])
sns.jointplot(x=data['uv'], y=data['tradeMoney'])
从这两张图可以看到pv和uv与tradeMoney之间并没有什么关系,将图片横纵坐标范围缩小看一下:
sns.jointplot(x=data[(data['pv'] < 200000) & (data['tradeMoney'] < 30000)]['pv'], y=data[(data['pv'] < 200000) & (data['tradeMoney'] < 30000)]['tradeMoney'])
看见此图我的内心想法是:什么鬼。我认为这张图的作用是告诉我pv和tradeMoney之间并没有什么关系,放弃插值这条路,选择删掉这18个样本。(其实在实战中我如果遇到这种比例的缺失数据,不bb果断直接删除,这里只是熟悉一下画图的方法哈哈)
附上Datawhale大佬的参考资料:
根据任务一,直接找到的缺失值情况是pu和pv;但是,根据特征nunique分布的分析,可以发现rentType存在"–“的情况,这也算是一种缺失值。
此外,诸如rentType的"未知方式”;houseToward的"暂无数据"等,本质上也算是一种缺失值,但是对于这些缺失方式,我们可以把它当做是特殊的一类处理,而不需要去主动修改或填充值。
将rentType的"–“转换成"未知方式"类别;
pv/pu的缺失值用均值填充;
buildYear存在"暂无信息”,将其用众数填充。
对houseTowar字段进行描述data.houseToward.value_counts()
发现数据中存在963条“暂无数据”这一类,不能删除(因为最好不要随意删除数据,毕竟数据很宝贵啊,之前那18条无所谓了。。但其他字段再不能删了),在one-hot编码处理时把它当作单独一类就可以了。
异常值处理
可以先绘制各特征的箱型图,从图中大致了解有无异常值:
# data数据剔除了object对象,目前有39列
sns.set(style="whitegrid")
fig, axes = plt.subplots(13, 3, figsize=(20, 40)) # 使图像以13行3列的样式展示
fig.set_size_inches(20, 60)
for i in range(3): # 3为列数
for j in range(13): # 13为行数,分别每一列每一列画图
sns.boxplot(data.iloc[:, 3*j+i], ax=axes[j][i]) # 这里第一列展示的图片分别是data的第0,3,6,9...个特征,故为3*j, +i是为了画第二列第三列
然后就可以根据各特征的箱型图,分别剔除异常值了。