文章目录
- 一、数据预处理
- 1、删除多余列
- 2、缺失值、异常值处理
- 二、 数据探索分析
- 1、DistanceKM与房价关系
- 2、14岁及以下比重与房价关系
- 3、自驾实际值与房价关系
- 4、65岁及以上比重与房价关系
- 5、人口占比与房价关系
- 三、机器学习预测房价
- 1、模型选择
- 2、模型调参
- 四、总结
一、数据预处理
使用jupter book载入训练数据
import numpy as np
import pandas as pd
import re
import matplotlib.pyplot as plt
from pylab import mpl
mpl.rcParams['font.sans-serif'] = ['FangSong'] # 指定默认字体
data=pd.read_excel(r'C:\Users\Administrator\Desktop\house\train.xlsx')
data.head()
数据有62个特征值,观察后发现数据中有不少缺失值,并且存在很多信息冗余的特征,有必要对其逐一分析:
1、删除多余列
首先id列以及板块列作为标识列可以作直接删除处理
这些列表示都是人口特征,其中存在信息冗余,人数和比重保留其一即可,这里我选择保留比重数据
这些列表示的是房屋所在区域的配套设施数量分布,其中优势配套分布列并没有提供额外的信息,对于建模来说意义不大,可以做删除处理。
接下来的这几列表示的是房屋的交通便利情况,这里住户数量和路口数量特征绝大多数为0,判断为缺失值,做删除处理。 自驾和自驾实际值表示含义未可知,两者之间差距比较大,应该是量级不一致导致的。这里我们只保留一个自驾实际值。公共交通我们也只保留一个实际值;
这几列表示一些民生部门的数量分布,其中优势分布属于信息冗余,我们将其删除
最高房价列和房价中位数列由于缺失值太多只能做删除处理
这几列表示房屋附近产业分布,占比和数量我们保留其一即可,这里选择保留数量。优势产业为信息冗余直接删除
这几列房屋所在区域氛围,优势氛围列信息冗余,做删除处理
后面这几列同样缺失比例过大,做删除处理
这几列,与前面的氛围列数据重合了,作删除处理
columns=['人口占比', '14岁及以下比重', '15至64岁比重', '65岁及以上比重','成人高等学校', '医院数量', '中学', '普通高等院校', '幼儿园', '景观数量', '小学','自驾实际值','公共交通实际值', '生产生活服务部门数量','科学素质提高部门数量', '党政机关数量', '流通数量', '第一产业数量','第二产业数量','第三产业数量','住宅氛围', '办公氛围', '商业氛围', '工厂氛围','DistanceKM', '房价']
data_.loc[:,columns]new=data
删除多余的列之后,现在只有26列,分析难度大大降低
2、缺失值、异常值处理
对于人口特征’人口占比’, ‘14岁及以下比重’, ‘15至64岁比重’, '65岁及以上比重’这几列来说,数值为0的应该表示的是缺失值,这里我们使用均值来代替
自驾实际值和公共交通这两列也有不少0值,其实这两列值代表的含义并不可知,这里姑且也用平均值去代替
peoplecolumns=['人口占比', '14岁及以下比重', '15至64岁比重', '65岁及以上比重','自驾实际值','公共交通实际值']
for i in peoplecolumns:data.loc[data[i]==0,i]=data[i].mean()
我们看一下房价分布的箱线图:
fig=plt.figure(dpi=400)
data.boxplot(column='房价', whis=1.5)
plt.title("房屋价格分析(箱形图)")
plt.show()
很明显有一个离群点,虽然这并不意味着这是异常值,它可能是别墅或者其他什么原因导致的价格偏高,但是这会对建模产生影响,我们需要将其删除
二、 数据探索分析
我们先看一下房价的整体分布
price = data['房价']
max_price = price.max()
min_price = price.min()
mean_price = price.mean()
median_price = price.median()print("最高价格:%.2f元/平方米" %max_price)
print("最低价格:%.2f元/平方米" %min_price)
print("平均价格:%.2f元/平方米" %mean_price)
print("中位数价格:%.2f元/平方米" %median_price)
可以看到房价最高价格为20000元,而最低价格为4450元,均值为8464元,这可能是一个中小城市的房价分布
plt.figure(dpi=200)
plt.xlim(0,30000)
plt.ylim(0,300)
plt.title("房屋价格分析")
plt.xlabel("房屋价格 (元/平方米)")
plt.ylabel("房屋数量")
plt.hist(price, bins=60)
plt.vlines(mean_price, 0, 300, color='red', label='平均价格', linewidth=1.5, linestyle='--')
plt.vlines(median_price, 0, 300, color='red',label='中位数价格', linewidth=1.5)
plt.legend()
从图中可以看到,房屋价格呈明显的双峰分布,集中在5000元和1万元两处。而房价的中位数与平均值差距很小,意味着房价的分布较为均匀。
接下来我们分析下具体的特征与房价之间的关系,因为特征数较多,我们这里只取最重要的五项特征进行分析。
首先使用xgboost算法计算特征重要度
import xgboost as xgb
model = xgb.XGBRegressor(max_depth=5, learning_rate=0.1, n_estimators=160, silent=True, objective='reg:gamma')
from xgboost import plot_importance
model.fit(data_new.loc[:,data_new.columns!="房价"], data_new.loc[:,"房价"])
fig, ax = plt.subplots(1,1,figsize=(10,5),dpi=200)
plot_importance(model,ax=ax,max_num_features=5)
可以看到DistanceKM、14岁及以下比重、自驾实际值、65岁及以上比重、人口占比这五项对于房价的影响是最重要的
1、DistanceKM与房价关系
我们使用seaborn中的regplot作图函数,可以描绘两列数据的散点图,同时可以自动拟合它们之间的关系
plt.figure(dpi=200)
sns.regplot(x="DistanceKM",y="房价",data=data_new,color="g")
可以看到随着距市中心距离的提升,房价呈现下降的趋势,这与我们的常识相符合
2、14岁及以下比重与房价关系
plt.figure(dpi=200)javascript
sns.regplot(x="14岁及以下比重",y="房价",label="14岁及以下比重",data=data_new,color="b")
可以看到随着14岁以下占比的提高,房价有明显上升趋势,这可能是因为青少年集中的区域其教育资源一般较为密集,房价也会偏高
3、自驾实际值与房价关系
plt.figure(dpi=200)
sns.regplot(x="自驾实际值",y="房价",label="14岁及以下比重",data=data_new,color="b")
随着自驾实际值的提升,房价呈下降趋势,此处自驾值的具体含义并不可知,其原因也无法探究
4、65岁及以上比重与房价关系
plt.figure(dpi=200)
sns.regplot(x="65岁及以上比重",y="房价",data=data_new,color="b")
可以看到随着65岁及以上比重的提高,房价也呈现上升趋势。一方面可能是因为老年人财富积累高,能承担高房价。另一方面是老年人居住地一般为老城区,房价一般来说比新城区要高。
5、人口占比与房价关系
我们将人口占比分为四个区间’人口稀疏’,‘人口较稀疏’,‘人口较密集’,‘人口密集’,分析其与房价的关系
data["peoplesize"]=pd.qcut(data["人口占比"],4,labels=['人口稀疏','人口较稀疏','人口较密集','人口密集'])
plt.figure(dpi=200)
data.groupby("peoplesize")["房价"].mean().sort_values(ascending=False).plot(kind="bar")
plt.xlabel("人口密集程度")
plt.ylabel("房屋平均价格(元/平方米)")
虽然变化不是很明显,但是还是可以看出人口稀疏的地方房价反而要比人口密集的地方要多,这似乎与我们的常识不想符合,可能是因为该城市工厂数量较多,所在区域人群密度较高,而工厂位置一般位于郊区,导致房价偏低、
三、机器学习预测房价
1、模型选择
对数据进行以下处理:确定特征与标签、分割数据以及归一化处理
x=data_new.loc[:,data_new.columns!="房价"]
y=data_new.loc[:,'房价']from sklearn.model_selection import train_test_split
x_train, x_test, y_train, y_test = train_test_split(x, y, random_state=40, test_size=0.3)
from sklearn.preprocessing import MinMaxScaler
ss_x = MinMaxScaler()
x_train = ss_x.fit_transform(x_train)
x_test = ss_x.transform(x_test)
分别调用sklearn库中相应的模块,建立随机森林回归、极端随机森林回归、xgboost模型,并在训练集上训练模型,然后在测试集上预测二手房的房价,使用r2-score评估模型精度
from sklearn.ensemble import RandomForestRegressor
from sklearn.metrics import r2_score
from sklearn.ensemble import ExtraTreesRegressor
import xgboost as xgb
rfr=RandomForestRegressor()
etr=ExtraTreesRegressor()
xg=xgb.XGBRegressor()
rfr.fit(x_train,y_train)
etr.fit(x_train,y_train)
xg.fit(x_train,y_train)
print('随机森林回归模型的r2-score为:',r2_score(rfr.predict(x_test),y_test))
print('极端随机森林模型的r2-score为:',r2_score(etr.predict(x_test),y_test))
print('xgboost模型的r2-score为:',r2_score(xg.predict(x_test),y_test))
可以看到极端随机森林模型的表现要更好一点,所以我们选择极端随机森林算法建立房价预测模型
2、模型调参
对极端随机森林算法进行调参,这里参数选取**‘max_depth’,‘n_estimators’**两个参数进行调参,它们分别代表决策树的深度以及模型迭代次数
from sklearn.model_selection import GridSearchCV
estimator = etrparam_grid = {'max_depth':[10,20,30], 'n_estimators': [10,50,100]
}
ETR=GridSearchCV(estimator,param_grid)
ETR.fit(x, y)
print('Best parameters found by grid search are:', ETR.best_params_)
当模型参数为’max_depth’: 30, ‘n_estimators’: 50时,模型的拟合效果最好,我们最终采用此模型预测房价
这是我们预测的房价整体分布,房价呈现正态分布,中位数与平均数相近,房价分布均匀。
四、总结
本项目对给出的房价数据进行了分析建模,首先对数据进行预处理,减少了不必要的特征,以及对缺失值、异常值进行了处理。然后采用统计分析的方法对数据进行初步分析,大致了解房价分布及其影响因素;最后采用机器学习方法建模预测,并比较了几种常用回归模型的预测效果。由于时间有限,本次数据分析项目还有很多可供优化的方面,如缺失值、异常值的处理可以如使用算法建模填充,模型的选择、调优可以再添加几组对照