news 2026/9/2 8:43:32

上海二手房挂牌总价预测与市场特征分析

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
上海二手房挂牌总价预测与市场特征分析

1 研究背景与目标

二手房挂牌价格同时受到区位、面积、户型、楼龄、楼层、朝向、装修与配套等因素影响。结构化数据分析可以帮助识别市场中主要价格梯度,并建立可重复的基准估价流程。本案例不追求复杂算法,而是用清晰的数据清洗、可解释特征和常见回归模型展示完整分析链路。

1.1 研究目标

  • 构建可直接在 Jupyter Notebook 中运行的上海二手房分析流程。
  • 将房源描述解析为户型、面积、楼层、朝向及文本卖点标签。
  • 比较简单回归模型,并从多项指标评价预测质量。
  • 逐图解释市场现象、可能原因及对建模的影响。
  • 识别目标泄漏、样本偏差和挂牌价与成交价差异等局限。

2 数据来源与字段说明

交付数据整理自公开的上海链家二手房挂牌数据仓库。案例主题和分析结构参考 Kaggle 上的上海二手房价格数据集与常见房价预测流程。原始字段包含房源标题、区县、板块、小区、户型描述、挂牌总价、单位面积价格和建成年份等。为便于本地复现,最终 CSV 已统一为 UTF-8 编码,并加入从文本中解析的结构化字段。

数据来源说明:挂牌信息反映采集时点的卖方报价,不代表最终成交价;采集时间、覆盖范围和挂牌重复更新可能影响样本代表性。报告中的价格分析仅描述本数据集,不外推为当前上海全市场价格水平。

字段类别

主要字段

用途

位置字段

区县、板块、小区

分析空间差异;小区用于分组划分,不直接进入模型

房屋结构

室、厅、面积、总楼层、所在楼层、朝向

刻画房源物理属性

时间属性

建成年份、房龄

刻画楼龄及其非线性影响

价格字段

总价、单价

总价为目标;单价只用于探索,禁止进入模型

文本标签

地铁、南北通透、精装修、满五、采光等

从标题提取可解释的0/1卖点特征

3 数据清洗与特征工程

原始数据共73,316条、12个字段。清洗后保留70,613条记录,删除或排除2,703条明显异常或重复样本。主要规则包括:总价限定为50万至5000万元、面积限定为15至500平方米、总楼层限定为1至80层、单位面积价格限定为5000至250000元/平方米,并对关键结构字段进行正则解析。

3.1 目标泄漏控制

单位面积价格通常满足“单价≈总价÷面积”。若在预测总价时输入单价,模型几乎可以反推出目标,得到看似优秀但无法用于真实估价的成绩。因此单价仅用于描述性分析,绝不进入训练特征。

3.2 文本标签

对房源标题进行规则化关键词提取,形成地铁、南北通透、精装修、毛坯、满五、满二、采光、阳台、低楼层和景观等二元变量。该方法采用透明的关键词规则,容易解释、容易复现,也能保留部分非结构化信息。

4 探索性数据分析

4.1 清洗后字段缺失率

miss=(df.isna().mean()*100).sort_values(ascending=False); show=miss[miss>0] plt.figure(figsize=(9,5.4)); plt.barh(show.index,show.values,color=COLORS[0]); plt.xlabel('缺失比例(%)'); plt.ylabel('字段'); plt.title('清洗后字段缺失率'); plt.grid(axis='x',alpha=.2); plt.tight_layout(); plt.show()

清洗后的结构化数据仅“建成年份”和由其计算的“房龄”存在缺失,共2,514条,占3.6%。其余建模字段均已完整解析。建模时对年份类字段采用训练集内中位数填补,避免直接删除样本导致区域结构发生偏移。

4.2 上海二手房挂牌总价分布

4.3 各区县挂牌房源数量

浦东挂牌量最高,共16,947条,占样本的24.0%;闵行和宝山也具有较高样本量。金山、崇明和上海周边样本较少,因此这些区域的均价和模型误差更容易受个别房源影响,解读时不能只比较点估计。

4.4 房源建筑面积分布

房源面积中位数为81.0平方米,样本主体集中在中小户型区间,右侧仍有少量大面积改善型与豪宅房源。面积是总价最直接的数量基础,但面积与价格并非严格线性,位置和单价水平会造成相同面积房源的显著价差。

4.5 主要户型挂牌数量

4.6 主要朝向的挂牌单价中位数

朝向类别之间存在一定单价差异,但差异幅度明显小于区县和板块差异。朝向可以作为辅助特征,却不应被单独理解为决定性因素;其影响还可能与户型、楼层和采光标签共同发生。

4.7 文本标签与挂牌单价中位数差异

tag_cols=['地铁标签','南北通透标签','精装修标签','毛坯标签','满五标签','满二标签','采光标签','阳台标签','低楼层标签','景观标签']; rows=[] for t in tag_cols: m1=df.loc[df[t]==1,'单价_元每平'].median(); m0=df.loc[df[t]==0,'单价_元每平'].median(); rows.append((t.replace('标签',''),(m1/m0-1)*100)) s=pd.DataFrame(rows,columns=['标签','差异']).sort_values('差异'); plt.figure(figsize=(9,6)); plt.barh(s['标签'],s['差异'],color=[COLORS[3] if x<0 else COLORS[1] for x in s['差异']]); plt.axvline(0,color='#555555'); plt.xlabel('有标签房源相对单价差异(%)'); plt.ylabel('文本标签'); plt.title('文本标签与挂牌单价中位数差异'); plt.grid(axis='x',alpha=.2); plt.tight_layout(); plt.show()

不同标签房源的单价中位数存在正负差异,但这些差异并非严格因果效应。例如“低楼层”标签可能更多出现在老旧小区,“景观”标签可能集中在高价板块。标签适合用于提升预测,而不宜直接解释为标签本身带来的价格溢价。

4.8 主要数值特征相关性热力图

总价与面积呈较强正相关,单价与总价也相关,但单价由总价和面积计算得到,因此被明确排除出预测特征。建成年份与房龄几乎完全负相关,二者同时保留主要为了展示和树模型非线性切分;线性模型中标准化与正则化可缓解共线性影响。

5 建模方案

5.1 数据划分

采用 GroupShuffleSplit 按小区分组划分数据,训练集56,574条,测试集14,039条;训练集和测试集的小区交集为0。与普通随机划分相比,该方式更严格,能够检验模型对未在训练集中出现过的小区的泛化能力。

5.2 模型设置

模型

作用

主要设置

中位数基线

提供最低可接受参照

所有测试样本预测为训练集总价中位数

岭回归

可解释的线性基准

类别独热编码,数值标准化,L2正则化

决策树

学习非线性和特征交互

最大深度16,叶节点最少8条样本

随机森林

降低单棵树方差

80棵树,最大深度18,叶节点最少3条样本

5.3 评价指标

MAE反映平均绝对万元偏差;RMSE对大误差更敏感;R²衡量解释的方差比例;RMSLE更关注相对误差并降低高价样本支配;MAPE便于以百分比解释,但在低总价样本上更容易放大。

6 模型结果与误差分析

num_features=['室','厅','面积_平米','总楼层','建成年份','房龄_年','地铁标签','南北通透标签','精装修标签','毛坯标签','满五标签','满二标签','采光标签','阳台标签','低楼层标签','景观标签'] cat_features=['区县','板块','所在楼层','朝向'] X=df[num_features+cat_features]; y=df['总价_万元']; groups=df['小区'] split=GroupShuffleSplit(n_splits=1,test_size=0.2,random_state=42) train_idx,test_idx=next(split.split(X,y,groups)) X_train,X_test=X.iloc[train_idx],X.iloc[test_idx] y_train,y_test=y.iloc[train_idx],y.iloc[test_idx] y_train_log=np.log1p(y_train) print(f'训练集:{len(train_idx):,} 条;测试集:{len(test_idx):,} 条') print('训练/测试小区交集:',len(set(groups.iloc[train_idx]) & set(groups.iloc[test_idx]))) def evaluate(name,pred,rows,preds): pred=np.maximum(np.asarray(pred),0) rows.append({'模型':name,'MAE':mean_absolute_error(y_test,pred),'RMSE':mean_squared_error(y_test,pred)**0.5,'R²':r2_score(y_test,pred),'RMSLE':mean_squared_log_error(y_test,pred)**0.5,'MAPE':np.mean(np.abs((y_test-pred)/y_test))}) preds[name]=pred rows=[]; preds={} evaluate('中位数基线',np.repeat(y_train.median(),len(y_test)),rows,preds) num_pipe=Pipeline([('填补',SimpleImputer(strategy='median')),('标准化',StandardScaler())]) cat_pipe=Pipeline([('填补',SimpleImputer(strategy='most_frequent')),('编码',OneHotEncoder(handle_unknown='ignore',min_frequency=20))]) pre_linear=ColumnTransformer([('数值',num_pipe,num_features),('类别',cat_pipe,cat_features)]) ridge=Pipeline([('预处理',pre_linear),('模型',Ridge(alpha=10.0,solver='lsqr'))]) ridge.fit(X_train,y_train_log); evaluate('岭回归',np.expm1(ridge.predict(X_test)),rows,preds) num_tree=Pipeline([('填补',SimpleImputer(strategy='median'))]) cat_tree=Pipeline([('填补',SimpleImputer(strategy='most_frequent')),('编码',OrdinalEncoder(handle_unknown='use_encoded_value',unknown_value=-1))]) pre_tree=ColumnTransformer([('数值',num_tree,num_features),('类别',cat_tree,cat_features)]) tree=Pipeline([('预处理',pre_tree),('模型',DecisionTreeRegressor(max_depth=16,min_samples_leaf=8,random_state=42))]) tree.fit(X_train,y_train_log); evaluate('决策树',np.expm1(tree.predict(X_test)),rows,preds) rf=Pipeline([('预处理',pre_tree),('模型',RandomForestRegressor(n_estimators=80,max_depth=18,min_samples_leaf=3,max_features=0.75,random_state=42,n_jobs=-1))]) rf.fit(X_train,y_train_log); evaluate('随机森林',np.expm1(rf.predict(X_test)),rows,preds) results_df=pd.DataFrame(rows).sort_values('RMSE').reset_index(drop=True) display(results_df.style.format({'MAE':'{:.2f}','RMSE':'{:.2f}','R²':'{:.3f}','RMSLE':'{:.3f}','MAPE':'{:.2%}'})) best_name=results_df.iloc[0]['模型']; best_pred=preds[best_name]

模型

MAE

RMSE

RMSLE

MAPE

随机森林

72.8

139.2

0.875

0.180

13.0%

决策树

86.4

165.0

0.824

0.216

15.7%

岭回归

76.5

236.4

0.639

0.170

12.5%

中位数基线

232.6

413.8

-0.106

0.572

41.3%

6.1 不同模型的测试集误差对比

6.2 随机森林预测残差分布

6.3 随机森林主要特征重要性

面积、板块和区县等结构与位置变量通常位于重要性前列,符合二手房总价由“面积×区位价格水平”共同决定的市场逻辑。特征重要性表示模型分裂时的贡献,不等同于因果影响;特别是区县与板块存在层级关联,重要性会在相关变量之间分摊。

7 主要结论

  1. 清洗后数据包含70,613条房源,浦东、闵行和宝山挂牌样本较多,区域样本量差异明显。
  2. .。。。。。。。。。。。。。。。。。

8 局限性与改进方向

  • 挂牌价不等于成交价:卖方报价受到议价预期影响,不能直接代表真实交易价格。
  • 数据时间与覆盖范围有限:报告只描述交付数据集,不用于判断当前上海市场水平。
  • 具体细节见原文

    创造不易,谢谢各位多多点赞收藏!

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/2 8:43:21

STM32与OpenMV实现自动泊车:嵌入式视觉控制实战解析

简介&#xff1a;本资源是面向电子类竞赛选手与嵌入式初学者的南航电赛校赛自动泊车系统完整实现方案&#xff0c;基于STM32F103主控与OpenMV视觉模块协同开发&#xff0c;复现青岛2021市电赛控制类题目核心功能。资源包共201个文件&#xff0c;含36个头文件&#xff08;.h&…

作者头像 李华
网站建设 2026/9/2 8:39:19

Stable Diffusion本地部署全攻略:从环境配置到提示词实战

1. 先搞清楚这个“巧合”到底在说什么 看到“GPT-4训练四周年&#xff0c;Stable Diffusion同日巧合”这个标题&#xff0c;很多人第一反应可能是“这俩有什么关系&#xff1f;”。其实&#xff0c;这个“巧合”本身就是一个很好的切入点&#xff0c;它提醒我们&#xff0c;在A…

作者头像 李华
网站建设 2026/9/2 8:39:09

ASP商城系统源码解析:从安全漏洞到现代化改造实战

简介&#xff1a;这是一套基于ASP技术构建的完整在线商城系统源码&#xff0c;面向Web开发初学者与ASP技术学习者&#xff0c;帮助理解传统动态网站在电商场景下的架构设计与功能实现。资源共394个文件&#xff0c;包含193个核心ASP业务逻辑文件&#xff08;如商品管理、订单处…

作者头像 李华
网站建设 2026/9/2 8:38:28

第330篇 硬件在环测试——虚实结合的HIL验证

上篇聊了Gazebo仿真测试&#xff0c;在虚拟世界里跑算法。仿真有个前提假设&#xff1a;所有硬件行为都可以用数学模型近似。电机响应是理想的&#xff0c;传感器数据服从高斯噪声分布&#xff0c;通信延迟是固定的。但真实硬件不这么乖。电机驱动器有死区&#xff0c;编码器有…

作者头像 李华
网站建设 2026/9/2 8:37:43

Hibernate 5.5.8.Final 深度解析:企业级Java ORM的稳定选择与实战指南

简介&#xff1a;本资源为 Hibernate ORM 框架 5.5.8 Final 稳定发行版官方二进制与源码集成包&#xff0c;面向 Java 后端开发者、企业级应用架构师及 JPA 技术学习者&#xff0c;用于构建高可靠的数据持久层&#xff0c;解决对象关系映射、事务管理、缓存集成与数据库方言适配…

作者头像 李华
网站建设 2026/9/2 8:36:31

混响统计模型:从RT60到Polack实现的核心指南

简介&#xff1a;面向声学与信号处理领域的研究人员和工程师&#xff0c;这份混响统计模型资源提供了在 MATLAB 环境下针对海底混响的建模仿真方案&#xff0c;重点支持单频和线性调频信号&#xff0c;可服务于水下通信、海洋探测及声纳系统设计中的声学环境分析。压缩包内仅包…

作者头像 李华