设为首页|收藏本站|
开启左侧

[问答] 波士顿房价预测分析

[复制链接]
19298 0
正义力量 发表于 2022-4-9 11:50:35 | 只看该作者 打印 上一主题 下一主题
 
封面图来自Unsplash @zhang kAIyv
红烧肉是一名Python数据分析初学者,希望在每一次的数据分析中积累自己的学习过程,表达自己的观点,快速成长和迭代。以此篇作为开篇,如有待改进之处,请随时指出。
数据分析的学习之路,从Kaggle的基础项目开始,颇有一点机器学习入门的味道。这里多提一句,大家在学习新知识或新技能的路上,要牢记自己的学习目标:长期目标是什么?最急功近利的目标是什么?只有心里牢记目标,才能不会走偏,随时调整自己的学习计划。
波士顿房价预测是经典的数据分析/机器学习入门项目,我们都知道,房价一般会与房间面积的大小、房子所在的城市、房子的空间布局等因素有关。而房价预测的任务就是给定与房价相关因素的数据,通过这些数据预测出房子的价格。
在这个项目中,我学习到了数据分析的基本流程,以及每个流程中的核心方法,在这个过程中也踩了一些小坑,加深了分析的认知。以下流程为:数据预览、初识数据、数据预处理、特征工程、预测模型,在每个流程中,先总结以下代码逻辑,然后输出代码块(朴实无华的学习过程~)
数据预览

1. 加载数据
2. 查看数据例子、形状、特征
import pandas as pd
import warnings
warnings.filterwarnings("ignore")

data = pd.read_csv('https://labfile.oss.aliyuncs.com/courses/1363/HousePrice.csv')
data
波士顿房价预测分析 第1张图片
通过以上步骤简单查看数据是否加载正确,大概浏览特征的种类及其数据类型。
data.info()
波士顿房价预测分析 第2张图片

查看特征的基本情况和数据类型

data.shape
波士顿房价预测分析 第3张图片

确定有多少行,多少列

初识数据


  • 查看居住面积GrLivArea与房价的关系,通过画散点图直观判断
  • 查看OverallQual(表示房子的材料和成品的质量)与房价之间的关系,类别型特征可以画箱线图
  • 分析所有特征的相关性,并用热力图分析前10个特征的相关性
  • 绘制某些特征之间的散点图,观察它们之间的相关性


  • 导入绘图模块
  • 设置颜色
  • 图片风格设置为深色网格
  • 绘制散点图,添加横纵坐标
  • 删除异常点,重新绘图
import matplotlib.pyplot as plt
import seaborn as sns
%matplotlib inline

color = sns.color_palette()
sns.set_style('darkgrid')


fig, ax = plt.subplots()
ax.scatter(x=data['GrLivArea'], y=data['SalePrice'])

plt.xlabel('GrLivArea', fontsize=13)
plt.ylabel('SalePrice', fontsize=13)
plt.show()
波士顿房价预测分析 第4张图片

右下角有两个异常点

data_drop = data.drop(data[(data['GrLivArea']>4000) & (data['SalePrice']<300000)].index)

fig, ax = plt.subplots()
ax.scatter(x=data_drop['GrLivArea'], y=data_drop['SalePrice'])
plt.xlabel('GrLivArea', fontsize=13)
plt.ylabel('SalePrice', fontsize=13)
plt.show()
波士顿房价预测分析 第5张图片

删除了异常点

从以上散点图可以看出,房子居住面积和房价存在明显的正相关关系。散点图一般是用来查看两个数值特征是否存在相关关系最简便的可视化方式,而类别型数据则一般用箱线图来查看。

  • 将房价数据和房屋整体质量数据提取出来,合并成一个df
  • 绘制箱线图,设置y轴大小
dt = pd.concat([data_drop['SalePrice'], data_drop['OverallQual']], axis=1)

fig, ax = plt.subplots(figsize=(8, 6))  #大一点方便观察箱线图
f = sns.boxplot(x='OverallQual', y='SalePrice', data=dt)
f.axis(ymin=0, ymax=800000)
波士顿房价预测分析 第6张图片
从以上箱线图可以看出,房屋质量越高,房价的区间范围越高。抽取两个变量观察之后,我们可以想到直接计算所有变量之间的相关性,取出相关性最高的几个变量绘制热力图进行观察。

  • 获取数据中所有特征的相关矩阵
  • 获得相关性最高的k个特征
  • 获得相关性最高的k个特征的相关数据集,使用numpy
  • 设置图片文字大小
  • 绘制热力图
  • 设置xy轴
import numpy as np

k = 10
corrmat = data_drop.corr()
cols = corrmat.nlargest(k, 'SalePrice')['SalePrice'].index
cm = np.corrcoef(data_drop[cols].values.T)

sns.set(font_scale = 1.25)  #不是fontsize
hm = sns.heatmap(cm, cbar=True, annot=True, square=True, fmt='.2f',
                 annot_kws={'size':10},
                 xticklabels=cols.values,  #要有s,并且不是stick
                 yticklabels=cols.values)
plt.show()
波士顿房价预测分析 第7张图片
从热力图的第一行可以看出,与房价这个变量相关性最高的依次为:OverallQual房屋整体质量、GrLivArea房屋居住面积、TotalBsmtSF房屋整体占地面积、GarageCars车库停车数量、1stFlrSF一楼面积、GarageArea车库面积、FullBath洗手间数量、TotRmsAbvGrd房间总数、YearBuilt修建年限,可以看出,与房价紧密相关的因素主要是房屋面积的各种衍生变量以及停车相关的因素,主要是居家生活的最基本要素。再看看以上这些因素之间的相关性。

  • 恢复sns默认设置
  • 建立特征列表
  • 绘制散点图,大小设置为2.5
sns.set()

cols = ['SalePrice', 'OverallQual', 'GrLivArea',
        'GarageCars', 'TotalBsmtSF', 'FullBath', 'YearBuilt']
sns.pairplot(data_drop[cols], size=2.5)
plt.show()
波士顿房价预测分析 第8张图片
可以看出影响房价核心的相关因素为GrLivArea房屋居住面积、TotalBsmtSF房屋整体占地面积、YearBuilt修建年限,并且前两者间存在一定的相关性。
数据预处理


  • 删除无关的id列
  • 查看房价的定性分析
  • 绘制房价的分布图,确认是否正态分布
  • 绘制房价的Q-Q图,再次确认是否正态分布
  • 使用numpy平滑数据
Id=data.loc[:,'Id']   #ID先提取出来,后面合并表格要用
data_drop1 = data_drop.drop('Id', axis=1)
data_drop1.head()
波士顿房价预测分析 第9张图片
data_drop1['SalePrice'].describe()
波士顿房价预测分析 第10张图片

  • 导入scipy.stats的模块辅助
  • 绘制分布图,拟合标准正态分布
  • 计算均值和方差
  • 打印均值和方差
  • 把均值和方差添加到图片作为图例
  • 设置y轴
  • 设置标题
from scipy.stats import norm,skew

sns.distplot(data_drop1['SalePrice'], fit=norm)

(mu, sigma) = norm.fit(data_drop1['SalePrice'])

print('\n mu = {:.2f} and sigma = {:.2f} \n'.format(mu, sigma))

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

波士顿房价预测分析 第11张图片

可以看出数据不是正态分布


  • 导入stats模块
  • 利用plt绘制Q-Q图
from scipy import stats

fig = plt.figure()
res = stats.probplot(data_drop1['SalePrice'], plot=plt)
plt.show()
波士顿房价预测分析 第12张图片

进一步确认数据不处于正态分布


  • 一般预测模型都会选用机器学习算法,而许多机器学习算法都是基于数据是高斯分布的条件下推导出来的,因此,这里先把房价处理成为高斯分布的形式
  • 使用 NumPy 提供的数据平滑接口来实现
  • 重新画出分布图
  • 重新计算均值和方差
  • 重新绘制Q-Q图
data_drop1['SalePrice'] = np.log1p(data_drop1['SalePrice'])  #把数据转为log(x+1),log1p的逆运算为expm1

sns.distplot(data_drop1['SalePrice'], fit=norm)

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

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

fig = plt.figure()
res = stats.probplot(data_drop1['SalePrice'], plot=plt)
plt.show()
波士顿房价预测分析 第13张图片

波士顿房价预测分析 第14张图片

平滑后的数据处于正态分布

特征工程


  • 查看缺失值
  • 填充缺失值
  • 转化数据类型,补充完整数据
  • 计算数值型特征的偏度
  • 利用BoxCox矫正特征
  • 对类别型特征进行One-Hot编码


  • 查看特征缺失值,提取前20个
  • 计算特征缺失率,删除缺失率为0的部分,排序提取前30个,利用字典生成一个dataframe,展示前20个
  • 可视化缺失率,绘制直方图,设置x轴图表旋转角度,绘制图,设置xy轴标注,设置标题
data_drop1.isnull().sum().sort_values(ascending=False)[:20]

data_na = (data_drop1.isnull().sum()/len(data)) * 100

data_na = data_na.drop(data_na[data_na==0].index).sort_values(ascending=False)[:30]

missing_data = pd.DataFrame({'Missing Raio': data_na})
missing_data.head(20)
波士顿房价预测分析 第15张图片

泳池等数据缺失,缺失率更能解释事实

fig, ax = plt.subplots(figsize=(15, 6))
plt.xticks(rotation='90')

sns.barplot(x=data_na.index, y=data_na)

plt.xlabel('Featurea', fontsize=15)
plt.ylabel('Percent of missing values', fontsize=15)
plt.title('Percent missing data by feature', fontsize=15)
波士顿房价预测分析 第16张图片

  • 类别型特征,填充None:除了 PoolQC 列,还有很多情况类似的列,例如房子贴砖的类型等。因此,对这些类别特征的列都填充 None
  • 数值型特征,填充0:对这些类似于车库的面积和地下室面积相关数值型特征的列填充 0 ,表示没有车库和地下室
  • 个别特征,填充中值:LotFrontage 表示与街道的距离,每个房子到街道的距离可能会很相似,因此这里采用附近房子到街道距离的中值来进行填充,使用groupby对街区进行分组,再用transform进行填充
  • 个别特征,填充众数:MSZoning 表示分区分类,这里使用众数来填充
  • 删除不相关列:Utilities 列与所要预测的 SalePrice 列不怎么相关,这里直接删除该列
  • 个别特征,填充常值:Functional 表示功能,数据描述里说缺失值代表房子具有基本的功能
  • 再次统计数据集中的缺失值
feature = ['PoolQC', 'MiscFeature', 'Alley', 'Fence',
           'FireplaceQu', 'GarageType', 'GarageFinish',
           'GarageQual', 'GarageCond', 'BsmtQual',
           'BsmtCond', 'BsmtExposure', 'BsmtFinType1',
           'BsmtFinType2', 'MasVnrType', 'MSSubClass']
for col in feature:
    data_drop1[col] = data_drop1[col].fillna('None')


feature = ['GarageYrBlt', 'GarageArea', 'GarageCars',
           'BsmtFinSF1', 'BsmtFinSF2', 'BsmtUnfSF',
           'TotalBsmtSF', 'BsmtFullBath', 'BsmtHalfBath',
           'MasVnrArea', 'Electrical']
for col in feature:
    data_drop1[col] = data_drop1[col].fillna(0)

data_drop1['LotFrontage'] = data_drop1.groupby('Neighborhood')['LotFrontage'].transform(lambda x: x.fillna(x.median()))

data_drop1['MSZoning'] = data_drop1['MSZoning'].fillna(data_drop1['MSZoning'].mode()[0])

data_drop2 = data_drop1.drop(['Utilities'], axis=1)

data_drop2['Functional'] = data_drop2['Functional'].fillna('Typ')

data_drop2.isnull().sum().sort_values(ascending=False)[:20]
#全部缺失值填充完毕

  • 部分数值型特征转为类别型:在数据集中有一些特征属于类别型特征,但却用数值来表示,例如销售月份。因此,要转换其成为类别型特征,使用apply方法
  • 部分类别型特征转为数值型:对一些类别型的特征列进行编码。将其转换成为用数值来表示的类别型特征,使用sklearn预处理的编码器
  • 增加房子总面积特征:因为数据没有给出房子的总面积,也就是说没有统计出一楼、二楼以及地下室的总面积。不过我们可以通过数据集来手动提取这一特征
feature = ['MSSubClass', 'OverallCond', 'YrSold', 'MoSold']
for col in feature:
    data_drop2[col] = data_drop2[col].apply(str)


from sklearn.preprocessing import LabelEncoder

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']
for col in cols:
    lbl = LabelEncoder()
    lbl.fit(list(data_drop2[col].values))
    data_drop2[col] = lbl.transform(list(data_drop2[col].values))

data_drop2['TotalSF'] = data_drop2['TotalBsmtSF'] + data_drop2['1stFlrSF'] + data_drop2['2ndFlrSF']

data_drop2[cols].head()
波士顿房价预测分析 第17张图片

  • 通过scipy的skew接口,判断数值型特征的偏度,是否符合正态分布:根据数据类型,提取这些特征;通过apply方法,使用skew逐一计算偏度,需要先去除缺失值,然后对偏度进行排序;生成一个dataframe
  • 偏度越大,越偏离正态分布,使用BoxCox方法平滑数据:利用scipy的special模块中的函数;选出偏度绝对值大于0.75的数据;找出这些偏度对应的特征;将偏度平滑至0.15
  • 对类别型特征,利用One-Hot进行编码:把数据分为自变量和因变量;计算所有因变量的虚拟数
numeric_feats = data_drop2.dtypes[data_drop2.dtypes != 'object'].index

skewed_feats = data_drop2[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()
波士顿房价预测分析 第18张图片
from scipy.special import boxcox1p

skewness = skewness[abs(skewness) > 0.75]
skewed_features = skewness.index

lam = 0.15
for col in skewed_features:
    data_drop2[col] = boxcox1p(data_drop2[col], lam)  #这里还包含房价,逆函数是inv_boxcox1p()


data_y = data_drop2['SalePrice']
data_x = data_drop2.drop(['SalePrice'], axis=1)

data_x_oh = pd.get_dummies(data_x)
print(data_x_oh.shape)  #输出(1458, 221)
预测模型


  • 划分数据集
  • 构建模型进行训练
  • 进行预测并评估


  • 将dataframe数据转为numpy数组
  • 选用 70% 的数据来训练,选用 30% 的数据来测试:计算数据总长度,根据长度的百分比进行划分
data_y_v = data_y.values
data_x_oh_v = data_x_oh.values
length = int(len(data_y) * 0.7)

train_y = data_y_v[:length]
train_x = data_x_oh_v[:length]
test_y = data_y_v[length:]
test_x = data_x_oh_v[length:]

  • 导入训练模型,这里只选用了线性回归模型,可以对比多个模型,并选择最合适的配比
  • 导入用于评测预测结果的均方差矩阵计算
#from sklearn.linear_model import Lasso
from sklearn.linear_model import LinearRegression
#from xgboost import XGBRegressor
from sklearn.metrics import mean_squared_error

model = LinearRegression()
model.fit(train_x, train_y)

y_pred = model.predict(test_x)
mean_squared_error(test_y, y_pred)细心可以留意,房价这个数据经过了两次变换,所以如果要查看最后的预测结果,需要进行两次逆运算。
from scipy.special import inv_boxcox1p

re = inv_boxcox1p(y_pred, lam)
final = np.expm1(re)
final[:5]array([210304.94920629, 117621.47389038, 189694.0373329 , 264136.60687635,
       115227.83940533])
由于在刚开始的数据预处理当中,删除了两个异常点,所以最后的预测结果数据与最开始的Id数据不匹配,这里就没有做最后的整合。
以上仅对房价预测做基础的数据分析过程,没有过多对数学原理和模型调优进行深入。希望可以通过进一步的练习提高各方面能力的应用。


上一篇:同样是滨海城市,为何上海空气湿度大,波士顿的空气却比较 ...
下一篇:Tufts2022入学新生群
@



1.西兔生活网 CTLIVES 内容全部来自网络;
2.版权归原网站或原作者所有;
3.内容与本站立场无关;
4.若涉及侵权或有疑义,请点击“举报”按钮,其他联系方式或无法及时处理。
 
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

排行榜
活跃网友
返回顶部快速回复上一主题下一主题返回列表APP下载手机访问
Copyright © 2016-2028 CTLIVES.COM All Rights Reserved.  西兔生活网  小黑屋| GMT+8, 2024-4-28 16:23