房地产业是国民经济的支柱产业,与大部分行业都有紧密联系。合理的房地产价格是保持社会和谐和保障民生的关键。本文旨在利用大数据技术与机器学习模型对xx市不同类型的二手房在2024年的房价进行预测,为购房者、房产开发商提供二手房较为详细的价格指导。房价的预测对于购房者和房屋投资者而言,有助于他们作出更合理的购房或投资决策;对于开发商而言,可以为市场策略提供参考。
为实现xx市二手房2024年房价的预测,首先通过对文献期刊的深入研究,选取与房价密切相关的关键特征作为影响因素,并在此基础上通过Python网络爬取技术收集并整理了xx市二手房市场的交易数据,包括房屋类型、房屋户型、建筑面积、建筑年代、装修程度等特征,以及重要的历史交易价格和交易时间。其次在数据处理过程中,先对原始数据进行了清洗、预处理以及标准化来消除异常值、缺失值和量纲差异的影响。利用大数据分析和机器学习技术,特别是Pyspark分布式处理框架,结合随机森林和GBDT决策树两种算法,对收集到的数据进行建模和模型评估优化。
一、数据采集与预处理
1. 数据采集
使用Python网络爬虫技术爬取链家网站中xx市二手房成交房屋数据信息、并进行数据预处理以及标准化,本次爬取数据使用Python主流的爬虫三大库包中的Lxml库,Lxml库的作用和BeautifulSoup库的作用类似,也是用于解析和提取数据,但是其解析速度比BeautifulSoup库更快。
具体方式:进入链家网站主页,获取网站的URL地址。通过get方式发送requests请求来实现数据爬取。本文通过登录网址来获取网站cookie来进行模拟登录操作,获取响应。使用Lxml库进行解析,因为Lxml的性能较高,爬取数据更加方便快捷。将所获取的数据进行保存,本文实验数据的保存格式为CSV文件。
在数据保存过程中,采用通配符的方式筛选关键信息,代码如下所示。
"""解析单个房源信息"""
patterns = {
'面积': r'(\d+\.?\d*)平米|㎡',
'房间': r'(\d*室\d*厅)',
'朝向': r'(东|西|南|北|东南|东北|西南|西北)',
'装修': r'(精装|简装|毛坯|其他)',
# '楼层': r'(\d+|低楼层|中楼层|高楼层)\(共(\d+)层\)',
'楼层': r'((?:低楼层|中楼层|高楼层|地下室(?:\s*\(共\d+层\))?|\d+层))',
'建房年份': r'(\d{4})年',
'房屋结构': r'(板楼|塔楼|板塔结合)',
}
爬取部分数据如图所示。
2. 数据预处理
① 在数据预处理阶段,由于数据爬取是按区分别保存在CSV文件中,所以需要先把爬取好的数据进行合并。
②数据清洗
a.去除空缺值
由于数据集收集数据较多,但部分属性存在空缺值,因此,直接将缺失值数量大于3的行进行删除,将其余空缺值采用众数或其他方式进行填充。(后续代码均为使用pyspark操作)。
from pyspark.sql.functions import col, when, isnan, lit
columns = df.columns
# 针对每列,计算该列是否缺失(null或nan)
# 注意字符串列不需要 isnan 判断(isnan只支持数值列)
# 先构建一个判断缺失的表达式列表
exprs = []
for c in columns:
# 尝试用 isNull 判断,数值列用 isnan 判断,字符串列跳过 isnan
# 先用 try 捕获判断列数据类型
try:
df.select(col(c).cast("double")).collect()
# 可以cast成double,认为是数值列,加 isnan 判断
exprs.append(when(col(c).isNull() | isnan(col(c)), 1).otherwise(0))
except:
# 字符串列,只判断 null
exprs.append(when(col(c).isNull(), 1).otherwise(0))
# 用 reduce 连加,求出每行缺失列数总和
from functools import reduce
from operator import add
missing_count_col = reduce(add, exprs)
df_with_missing = df.withColumn("missing_count", missing_count_col)
# 计算最大、平均缺失数量
max_missing = df_with_missing.agg({"missing_count": "max"}).collect()[0][0]
avg_missing = df_with_missing.agg({"missing_count": "avg"}).collect()[0][0]
print(f"每行最大空缺值数量: {max_missing}")
print(f"每行平均空缺值数量: {avg_missing:.2f}")
# 删除缺失值数量大于3的行
filtered_df = df_with_missing.filter(col("missing_count") <= 3).drop("missing_count")
print("过滤后行数:", filtered_df.count())
# 统计每列缺失值(null 包含)
from pyspark.sql.functions import count, isnan
missing_per_column = df.select([
count(when(col(c).isNull() | (isnan(col(c)) if df.schema[c].dataType.simpleString() in ['double', 'float'] else lit(False)), c)).alias(c)
for c in columns
])
print("每列空缺值数量:")
missing_per_column.show()
b.删除重复行
查看数据表头的列名,确保数据的完整性,并去除重复项,这里使用drop_duplicates() 方法用于删除数据集中的重复行
c. 特征工程--标签映射,部分代码如下:
from pyspark.sql.functions import udf
from pyspark.sql.types import IntegerType
# 定义字典
direction_mapping = {'东':1, '南':2, '西':3, '北':4}
renovation_mapping = {'精装':1, '简装':2, '其他':3, '毛坯':4}
structure_mapping = {'板楼':1, '塔楼':2, '板塔结合':3}
# 定义映射UDF
def map_value(mapping_dict):
def mapper(x):
if x in mapping_dict:
return mapping_dict[x]
else:
return None
return udf(mapper, IntegerType())
df_cleaned6 = df_cleaned6 \
.withColumn("朝向", map_value(direction_mapping)(col("朝向"))) \
.withColumn("装修", map_value(renovation_mapping)(col("装修"))) \
.withColumn("房屋结构", map_value(structure_mapping)(col("房屋结构")))
df_cleaned6.show(truncate=False)
print("目前行数:", df_cleaned6.count())
from pyspark.sql.functions import create_map, lit
from itertools import chain
region_mapping = {
'chaoyang': 1, 'haidian': 2, 'xicheng': 3, 'dongcheng': 4, 'changping': 5,
'huairou': 6, 'mentougou': 7, 'fangshan': 8, 'tongzhou': 9, 'shunyi': 10,
'daxing': 11, 'pinggu': 12, 'miyun': 13, 'yanqing': 14, 'shijingshan': 15,
'fengtai': 16
}
mapping_expr = create_map([lit(x) for x in chain(*region_mapping.items())])
df_cleaned8 = df_cleaned7.withColumn("region_numeric", mapping_expr.getItem(col("区域")))
df_cleaned8.select("区域", "region_numeric").show(10, truncate=False)
print("目前行数:", df_cleaned8.count())
最后处理完数据剩余17000+行数据。
二、基于Hadoop的分布式存储
具体Hadoop搭建,本文不做过多描述,后续会出专门一篇描述Hadoop的搭建和pyspark联合使用。
三、数据分析
1. 相关性分析
在本次数据分析过程中,我们采用了相关性分析方法来探索各个变量与价格之间的关系,并通过绘制相关性分析热力图来直观地呈现这些关系。
第一步:判断特征的数据分布。相关分析法主要有三个系数分别为:Pearson相关系数、Spearman秩相关系数以及Kendall's tau-b相关系数,其中Kendall相关系数用于判断数据一致性,而Pearson相关系数和Spearman秩相关系数的使用主要区别于数据是否满足正态分布,当数据满足正态分布时使用前者,反之,不满足正态分布时使用后者。所以第一步对预处理完的数据查看下其数据分布情况。分析步骤:1.对数据进行Shapiro-Wilk或者Kolmogorov–Smirnov检验,查看其显著性;2.若不呈现出显著性(P>0.05),说明符合正态分布,反之说明不符合正态分布。由于样本数数量大于5000,故使用Kolmogorov–Smirnov检验,结果显示所有特征均不符合正态分布。故使用Spearman相关系数
第二步:使用Spearman秩相关系数结合热力图对数据相关性进行可视化分析。结果如下图所示,结果解释:当|r|>0.95时,变量间存在显著性相关;当0.95>|r|>0.8时,变量间高度相关;当0.8>|r|>0.5时,变量间中度相关;当0.5>|r|>0.3时,变量间低度相关;当|r|<0.3时,变量间关系极弱,认为不相关。从第一张图中将|r|>0.3的变量筛选出,结果如图所示。
从热力图中可以看出,某些变量之间存在显著的正相关或负相关关系,这表明它们对价格有着重要的影响。
2. 数据可视化
部分数据可视化如图所示。
四、模型训练与评估
1. 评价指标:
本文所研究的房价预测实际选取的模型都是回归问题,所以本文选取了四个回归模型的评价指标,同时也是目前回归问题使用最多的评价指标:R2、MSE、MAE、RMSE。
a. R² (R-squared / 决定系数)
-
含义: 衡量模型解释因变量变异程度的能力。它表示模型能解释多少自变量(特征)的变化导致因变量(目标)的变化。取值范围在0到1之间(理论上可以小于0,表示模型比直接用均值预测还差)。越接近1,表示模型拟合效果越好,解释力越强。
b. MSE (Mean Squared Error / 均方误差)
-
含义: 所有数据点预测误差平方的平均值。它对较大的误差给予更高的惩罚。MSE越小,表示模型的预测值与实际值越接近,模型拟合效果越好。
c. MAE (Mean Absolute Error / 平均绝对误差)
-
含义: 所有数据点预测误差绝对值的平均值。它直接反映了预测值与实际值之间的平均绝对差距。MAE越小,表示模型的预测值与实际值越接近,模型拟合效果越好。相比于MSE,MAE对异常值不那么敏感。
d. RMSE (Root Mean Squared Error / 均方根误差)
-
含义: MSE的平方根。它将误差单位转换回与原始数据相同的单位,使其更易于解释。RMSE也像MSE一样对较大的误差比较敏感。RMSE越小,表示模型的预测值与实际值越接近,模型拟合效果越好。
2. 模型训练与评估
-
a. 数据准备与特征工程
-
定义了特征列(
feature_cols
)和标签列(label_col
),其中特征包括面积、单价、卧室数、客厅数、总房间数和区域编码,标签为总价。 -
使用
VectorAssembler
将特征列合并为向量列(features_raw
),并通过MinMaxScaler
对特征进行归一化处理,输出归一化后的特征列(features
)。
-
-
b. 数据集划分
-
将原始数据集按 8:2 的比例随机划分为训练集(
train_df
)和测试集(test_df
),并设置随机种子(seed=42
)以确保结果可复现。
-
-
c. 模型定义
-
定义了三种回归模型:
-
决策树回归(Decision Tree):基础树模型,用于对比。
-
随机森林回归(Random Forest):集成多个决策树,设置树数量为 100。
-
梯度提升树回归(GBDT):类似 XGBoost,设置迭代次数为 100。
-
-
将模型封装为元组列表(
models
),便于循环训练和评估。
-
-
d. 评估指标定义
-
使用
RegressionEvaluator
定义了三个评估指标:-
RMSE(均方根误差):衡量预测值与真实值的平均偏差,值越小越好。
-
R²(决定系数):衡量模型解释目标变量变异的比例,越接近 1 越好。
-
MAE(平均绝对误差):直接反映预测误差的平均绝对值,值越小越好。
-
-
-
e. 模型训练与评估循环
-
对每个模型执行以下步骤:
-
构建 Pipeline:将特征工程(
assembler
和scaler
)和模型(algo
)串联成 Pipeline。 -
训练模型:使用训练集拟合 Pipeline,生成模型对象。
-
预测与评估:在测试集上生成预测值,并计算 RMSE、R² 和 MAE。
-
特征重要性分析:提取模型(如随机森林或 GBDT)的特征重要性分数,并绘制条形图。
-
-
打印每个模型的评估结果,并保存特征重要性图表。
-
-
f. 结果汇总
-
将所有模型的评估结果(模型名称、RMSE、R²、MAE)存储为列表,并转换为 Pandas DataFrame 输出,便于对比分析。
-