北京二手房价格预测
本项目旨在通过数据科学方法对北京二手房价格进行预测。项目分为数据预处理、数据分析、模型建立与评估四个阶段。首先,对链家平台的二手房数据进行清洗和预处理,包括处理缺失值、删除重复数据以及调整分类变量。接着,通过描述性分析和可视化手段,探讨了区域、朝向、装修、房龄、面积等特征对房价的影响。最后,利用决策树和随机森林模型进行建模,并通过交叉验证评估模型性能。实例模拟部分预测了一套特定二手房的价格为894.66万元。
北京二手房价格预测
项目介绍
基于链家平台提供的北京二手房数据,对数据进行进一步的预处理工作,探讨各特征与房价之间的关联性,提取对房价影响较大的关键特征,深入剖析北京市二手房的定价规律,并构建房价预测模型。
数据预处理
读取数据
#导入库
import numpy as np
import pandas as pd
import random
from datetime import datetime
from matplotlib import pyplot as plt
import seaborn as sns
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import PolynomialFeatures
from sklearn.tree import DecisionTreeRegressor
from sklearn.linear_model import Lasso
from sklearn.ensemble import RandomForestRegressor
%matplotlib inline
plt.rcParams['font.sans-serif']=['SimHei']
plt.rcParams['axes.unicode_minus']=False
df=pd.read_csv(r'D:\BI study download\lianjia\lianjia.csv')
df.head()

Direction:方位信息
District:区域信息
Elevator:电梯状态描述
Floor:楼层信息
Garden:楼盘位置
Id:房屋编号
Layout:户型类型
Price:价格信息
Region:行政区划
Renovation:装修状况描述
Size:面积数据
Year:建造时间信息
df.info()

在分析数据时发现,Elevator字段存在大量缺失值,其中,NAN值表示无电梯,因此,将缺失值替换为'无电梯'。
df['Elevator'].fillna('无电梯',inplace=True)
删除重复值
df.drop_duplicates(inplace=True)
df.reset_index(drop=True, inplace=True)
数据分析
区域和价格的关系
df.describe()

fig,ax = plt.subplots(1,2,figsize=(16,6))
data0.boxplot(column=['Price'], flierprops={'markeredgecolor':'red', 'markersize':4}, ax=ax[0])
data0.boxplot(column=['Size'], flierprops={'markeredgecolor':'red', 'markersize':4}, ax=ax[1])

通过观察数据集,北京二手房的面积主要集中在15至200平方米,价格则主要集中在60万元至1.2亿元。价格最低的二手房为60万元,最高为6000万元;面积最小的为15平方米,最大的则为1019平方米。北京二手房的平均价格为607万元,平均面积约为99平方米。
df.drop(index = df[df['Price'] > 1200].index, inplace=True)
df.info()

可视化不同地区的房屋价格和数量
fig,ax = plt.subplots(2,1,figsize=(30,18))
x = data0['Region'].unique()
y0 = data0.groupby(by=['Region']).size().sort_values(ascending=False)
sns.barplot(x,y0,ax=ax[0],palette='Reds_d')
ax[0].set_title('北京各区二手房在售数量')
y1 = data0.groupby(by=['Region'])['Price'].mean().sort_values(ascending=False)
sns.barplot(x,y1,ax=ax[1],palette='Blues_r')
ax[1].set_title('北京各区二手房在售均价')

在北京市的二手房市场中,东城区的房源数量最多,紧随其后的是西城区和朝阳区,而石景山区则是最少的。房价分布与二手房数量分布呈现一致的排序,从东城区到石景山依次递减。这表明,二手房市场价格较高的区域往往伴随着较大的房屋供给量。高价区域的房屋价格均值与低价区域的差值显著,这表明地区因素对房价具有重要影响。
朝向和价格的关系
plt.figure(figsize=(30,8))
x = df['Direction'].unique()
y = df.groupby(by=['Direction'])['Price'].mean().sort_values(ascending=False)
x1=x[:20]
y1=y[:20]
sns.barplot(x1,y1,palette='Greens_r')

南北朝向的住宅平均售价最高,受到购房者选房时的偏好。由于南北朝向的房屋具有良好的采光性能,而其价格变动幅度较小。
装修和价格关系
plt.figure(figsize=(20,8))
x = df['Renovation'].unique()
y = df.groupby(by=['Renovation'])['Price'].mean().sort_values(ascending=False)
sns.barplot(x[:4],y[:4],palette='Reds_r')

精装修二手房售价最高,遵循市场法则。相比之下,轻装及毛坯房售价相近,差距不大。然而,其影响程度在一定程度上可忽略不计。
年龄和价格的关系
fig,ax = plt.subplots(2,1,figsize=(30,18))
x = df['age'].unique()
y0 = df.groupby(by=['age']).size().sort_values(ascending=False)
sns.barplot(x,y0,ax=ax[0],palette='Reds_d')
ax[0].set_title('北京各房龄二手房在售数量')
y1 = df.groupby(by=['age'])['Price'].mean().sort_values(ascending=False)
sns.barplot(x,y1,ax=ax[1],palette='Blues_r')
ax[1].set_title('北京各房龄二手房在售均价')

二手房的年龄主要集中在10至35年之间,较新的二手房供应量较少。在房屋价格方面,较新的二手房的平均价格低于10年以上房龄的二手房。值得注意的是,60年以上的老房子依然有较高的销售量,其价格也较为昂贵。
房型和价格的关系
#数量和户型的关系
plt.figure(figsize=(20,8))
x = df['Layout'].unique()
print(x)
y = df.groupby(by=['Layout']).size().sort_values(ascending=False)
sns.barplot(x[:10],y[:10],palette='Oranges'

plt.figure(figsize=(20,8))
x = df['Layout'].unique()
y = df.groupby(by=['Layout'])['Price'].mean().sort_values(ascending=False)
sns.barplot(x[:10],y[:10],palette='YlGn')

北京二手方市场的房型种类繁多,其中数量最多的是3室1厅的房型,排第二位的是2室1厅。1室1厅和2室2厅的数量较为接近,而0厅房型的二手房也排在前几位。从价格分布来看,其与房型数量的变化趋势基本一致,这表明市场需求主要集中在3室1厅、2室1厅、1室1厅以及2室2厅这几种房型。尽管各房型之间存在一定价格差异,但这些差异并不显著,因此对房价的影响相对较小。
相关性分析
删除无用数据
df1=df.dropna()
df1.drop(columns=['District','Garden','Id','Year','Direction','Layout'],inplace=True)
df1

df['Renovation'] = df['Renovation'].map({'毛坯':0,'简装':1,'精装':2,'其他':3})
df['Elevator'] = df['Elevator'].map({'无电梯':0,'有电梯':1})
map1 = {'东城':13, '西城':12, '朝阳':11, '海淀':10, '丰台':9, '昌平':8, '大兴':7, '房山':6, '门头沟':5, '顺义':4,
'亦庄开发区':3, '通州':2, '石景山':1}
df1['Region'] = df1['Region'].map(map1)
df.corr()[['Price']]

通过相关系数分析可以看出,面积对价格的影响最大,而房屋年龄、是否有电梯以及楼层位置的影响相对较小,装修方式对价格的影响程度最低。
数据建模
# 分割x,y
x = df.drop(columns=['Price'])
y = df['Price']
x_train, x_test, y_train, y_test = train_test_split(x, y,train_size=0.7)
#训练模型
#决策树
dt = DecisionTreeRegressor(max_depth = 9)
dt.fit(x_train,y_train)
print(round(dt.score(x_train,y_train),2))
print(round(dt.score(x_test,y_test),2))
训练集得分:0.83
测试集得分:0.76
#随机森林
rf = RandomForestRegressor()
rf.fit(x_train,y_train)
print(f'训练集得分:{round(rf.score(x_train,y_train),2)}')
print(f'测试集得分:{round(rf.score(x_test,y_test),2)}')
训练集得分:0.97
测试集得分:0.81
模型评估
from sklearn.metrics import mean_squared_error,explained_variance_score,mean_absolute_error,r2_score
y_dt_train_pred=dt.predict(x_train)
y_dt_test_pred=dt.predict(x_test)
print ("决策树模型评估--训练集:")
print ('训练r^2:',dt2.score(x_train,y_train))
print ('均方差',mean_squared_error(y_train,y_dt_train_pred))
print ('绝对差',mean_absolute_error(y_train,y_dt_train_pred))
print ('解释度',explained_variance_score(y_train,y_dt_train_pred))
print ("决策树模型评估--验证集:")
print ('验证r^2:',dt2.score(x_test,y_test))
print ('均方差',mean_squared_error(y_test,y_dt_test_pred))
print ('绝对差',mean_absolute_error(y_test,y_dt_test_pred))
print ('解释度',explained_variance_score(y_test,y_dt_test_pred))
决策树模型评估结果如下:
训练数据集的评估指标显示,训练r²值为0.8294930763481481,均方误差为8860.336245868666,平均绝对误差为67.93515170770496,模型对训练数据的解释能力达到了82.95%。
验证数据集的评估结果表明,验证r²值为0.7609894681294798,均方误差为12372.514039142869,平均绝对误差为80.04623630560512,模型在验证数据集上的解释能力为76.10%。
from sklearn.metrics import mean_squared_error,explained_variance_score,mean_absolute_error,r2_score
y_rf_train_pred=rf.predict(x_train)
y_rf_test_pred=rf.predict(x_test)
print ("随机森林模型评估--训练集:")
print ('训练r^2:',rf.score(x_train,y_train))
print ('均方差',mean_squared_error(y_train,y_rf_train_pred))
print ('绝对差',mean_absolute_error(y_train,y_rf_train_pred))
print ('解释度',explained_variance_score(y_train,y_rf_train_pred))
print ("决策树模型评估--验证集:")
print ('验证r^2:',rf.score(x_test,y_test))
print ('均方差',mean_squared_error(y_test,y_rf_test_pred))
print ('绝对差',mean_absolute_error(y_test,y_rf_test_pred))
print ('解释度',explained_variance_score(y_test,y_rf_test_pred))
随机森林模型评估–训练集:
训练集的决定系数为0.971018612989481,均方根误差为1506.0082504870181,平均绝对误差为25.9558480075792,模型解释力为0.9710206214565889。
验证集的决定系数为0.8149524957794424,均方根误差为9579.087691070848,平均绝对误差为67.22141777497437,模型解释力为0.8149560221079576。
在训练集和测试集上的准确率分别为0.97和0.81,均显著高于决策树模型。此外,随机森林模型的均方差和平均绝对偏差均低于决策树模型。
实例模拟
一名用户有意将其出售至二手房交易市场,其房屋的具体情况如下:该房屋配备有1部电梯,位于6楼,位于东城区13区,精装为2级,面积为100㎡,房龄为20年。预测在该数据集统计年度时,其在二手交易市场上的估价。
apply = np.array([1,6,13,2,100,20]).reshape(1,-1)
#poly_apply = poly.fit_transform(apply)
round(rf.predict(apply)[0],2)
894.66
预测该房屋的价格为894.66万元
