尧图网络 高端网站定制 · 原创设计
免费咨询热线
400-888-6620
免费获取方案
短租开放数据全流程分析:数据清洗到房价预测建模
做数据分析最怕什么不是不会调库而是拿到一堆真实数据后不知道从哪下手。我建议第一个完整项目就从某短租平台的开放数据开始这是某国际都市的房源数据字段覆盖价格、房型、位置、评论时间、可订天数既有连续数值又有分类文本还有缺失值和异常值。跑完“数据加载→清洗→探索性分析→建模→可视化→结论”这套全流程你对数据分析的理解会比刷十遍教程都深。这篇文章就是我做完该项目后整理的完整记录适合刚入门数据分析的读者也适合想把自己作品集做成全流程项目的同学参考。1. 项目整体设计与思路拆解1.1 为什么要拿“某国际都市短租开放数据”当练手项目我见过很多初学者学完 pandas 和 matplotlib 之后依然不会做项目主要原因就是练习数据太“干净”了。教程里的数据往往已经处理得整整齐齐而真实开放数据带给你的是最原始的状态价格字段带着货币符号和逗号日期列有缺失经纬度偶尔跑偏甚至同一个区域的写法都有好几种。这份短租数据完美满足了“真实数据”这个条件。选择这份数据还有几个现实理由免费公开且规模适中大约有几万条房源记录单机内存完全能跑不需要上分布式。字段类型丰富包括数值、类别、日期、文本、地理坐标覆盖主流分析场景。业务故事好讲价格、房型、区域、评论量可以直接转化为“什么因素影响房价”这类人人都关心的问题。数据有明显缺陷缺失值、异常值、重复值都真实存在这对练习数据清洗非常有价值。动手之前我给这个项目定了一个明确目标不只做描述性统计还要完成一个价格预测模型并且把结论讲给非技术同事听。目标清楚了后面每一步才不会跑偏。1.2 全流程分几步走目标怎么定整个项目我划分成六个阶段每个阶段有输入、输出和落地的检查点下面是我实际执行时用的表阶段核心动作关键输出检查点数据获取下载开放CSV文件确认字段含义原始数据表字段个数、行数是否合理数据清洗处理缺失值、异常值、类型转换干净的DataFrame缺失率为0或已标记特征工程构造距离、价格区间、活跃度等特征扩展特征后的数据表新特征是否有业务含义探索性分析分布、对比、相关性分析图表 初步结论能否支撑后续建模方向建模预测训练线性回归、随机森林模型与评估指标RMSE、R²是否可比结果呈现可视化 一页纸结论可交付报告非技术听众能否看懂在这个框架里建模不是终点能解释结论才是。所以我在探索性分析阶段就会记录一些关键问题比如是不是核心区房源更贵、整套房是不是比单间有明显溢价、评论多的房源价格会不会更高。这些问题之后都会成为建模时的验证项。1.3 分析口径先定好后面少返工真实项目里最容易返工的地方就是口径不清。这个项目里我把口径提前定了三件事价格口径只看每晚价格不处理清洁费和服务费避免口径混乱。区域粒度用“区域组”这一层做对比分析不细分到社区因为社区级别太碎样本量不均。房源类型按数据集里原有的三类房型处理不额外合并。这些口径看起来是小事但如果你做了一半才发现“低价房源其实是共享房间”回头重跑所有分析的代价会非常大。先花十分钟把口径固化下来是给后面的自己省时间。2. 数据获取与环境准备先把地基打牢2.1 数据从哪来字段长什么样这份开放数据通常以 CSV 格式提供文件名为listings.csv下载解压后直接读入即可。核心字段虽然在不同版本里略有差异但以下几个是必有的字段名中文含义类型使用场景price每晚价格字符串需清洗分析目标room_type房源类型类别分组对比neighbourhood_group所属区域组类别区域分析latitude / longitude经纬度浮点数地理可视化minimum_nights最少入住晚数整数异常值检测number_of_reviews评论总数整数活跃度指标reviews_per_month月均评论数浮点数活跃度指标last_review最近评论日期字符串/日期时间分析availability_365全年可订天数整数供应分析calculated_host_listings_count房东拥有房源数整数房东规模这些字段足够支撑一套完整分析。我会重点利用price、room_type、neighbourhood_group做业务分组再用latitude、longitude做空间分布展示。2.2 环境安装一个命令装齐所需库我的建议是直接用 Anaconda 创建一个隔离环境。这里演示我用的命令conda create -n data_analysis python3.10 -y conda activate data_analysis pip install pandas numpy matplotlib seaborn scikit-learn openpyxl注意版本问题scikit-learn新版本里mean_squared_error增加了squaredFalse参数可以直接返回 RMSE旧版本没有。如果你用的还是 0.x 版本的老环境建议升级到 1.x 或直接用np.sqrt(mean_squared_error(...))手动开方。2.3 第一眼体检加载数据后的5分钟内做什么拿到 CSV 之后不要急着清洗先做三件事看维度、看字段类型、看数值分布。import pandas as pd df pd.read_csv(listings.csv) print(数据规模, df.shape) df.head() print(df.dtypes) print(df.describe())这一步的产出不是多么漂亮的图表而是对数据质量形成一个整体判断。我当时跑完describe()后立刻发现两个问题price列的 min 居然是 0且有些价格高到离谱reviews_per_month存在大量缺失。这些问题会直接影响后续分析和建模所以记录到自己的问题清单里接下来逐一处理。3. 数据清洗与特征工程把脏数据变成能用的表3.1 缺失值处理先看业务含义再决定填还是删缺失值处理不能机械套用“均值填充”或“直接删除”。处理之前先弄清楚缺失为什么发生、缺失代表什么业务含义。当时列了缺失检查代码missing df.isna().sum() missing missing[missing 0] missing_percent (missing / len(df) * 100).round(2) print(pd.DataFrame({缺失数量: missing, 缺失占比%: missing_percent}))这份数据里比较容易出现缺失的字段集中在评论相关列last_review和reviews_per_month缺失的房源通常是上线后从来没有收到过评论。这类房源要么是太新要么入住率低、没人评价。缺失本身就是一个信号这个房源没有获得过用户反馈。我的处理方法是把reviews_per_month缺失值填 0表示“当前没有评论活跃度”把last_review缺失单独创建一个布尔特征has_review避免用一个假日期去填充干扰时间分析。这样既保留了缺失背后的业务信息又不影响后续建模。注意last_review不要随便填一个很早的日期否则后面做“距最近评论天数”时会造出大量异常值。3.2 异常值与类型修正价格里的“$”和超低价房源这个数据集的price列是字符串格式比如$150或者$1,200直接astype(float)会报错。洗价格是第一步也是后面所有分析的前提df[price] df[price].replace({r\$: , ,: }, regexTrue).astype(float)清洗之后立刻检查异常值。我当时用两种方式并行判断先看分布再看业务合理性。价格最小值出现了 0这明显是异常值价格上限用 99% 分位作为截断参考比写死一个“1000美元”更合理因为不同城市价格带差异很大固定阈值很容易误杀正常房源。valid_price df[price].between(10, df[price].quantile(0.99)) df df[valid_price]同时我也检查了minimum_nights把超过 365 天的极端值视为登记错误或非正常房源直接剔除。坐标异常值则通过过滤经纬度明显越界的记录处理。3.3 特征工程新增4个对价格分析有用的特征做完清洗我只做少量特征保证每一步都能讲清楚业务含义。新增了四个特征distance_to_center房源到全市房源几何中心点的距离用来量化位置对价格的影响。距离计算用球面距离公式避免直接用经纬度平面距离在大城市尺度下失真。has_review是否有评论0/1 布尔特征。days_since_last_review最近评论距离数据发布日期的天数衡量房源近期活跃度。host_listing_count直接复用原有字段但把大于 10 的截断为 10防止极端值影响模型。距离计算的核心函数如下import numpy as np def haversine_np(lat1, lon1, lat2, lon2): R 6371.0 dlat np.radians(lat2 - lat1) dlon np.radians(lon2 - lon1) a np.sin(dlat / 2) ** 2 np.cos(np.radians(lat1)) * np.cos(np.radians(lat2)) * np.sin(dlon / 2) ** 2 return R * 2 * np.arctan2(np.sqrt(a), np.sqrt(1 - a)) df[distance_to_center] haversine_np( df[latitude], df[longitude], df[latitude].median(), df[longitude].median() )选取中位数坐标作为中心参照避免被个别极端坐标带偏。4. 探索性数据分析EDA先看图再建模4.1 价格分布右偏数据别硬建模价格分布是这个项目里最重要的第一张图。直接画直方图会发现一个典型特征长尾向右拖得很远少量高端房源把均值拉得很高中位数却远低于均值。这时如果用原始价格做线性回归模型会被长尾样本带偏。我把价格做了自然对数变换让分布更接近正态后续模型的误差评估也更平稳。df[log_price] np.log1p(df[price])处理之后你会看到分布明显对称许多。这个变换不是硬凑数学而是给模型一个更合理的优化空间。后面预测结果要还原成原始价格时做一次np.expm1(pred)就能转回来。4.2 区域与房型哪个区最“金贵”按区域组和房型做分组统计能立刻看出市场结构。我用的分析思路是先看每个区域的房源数量占比再看该区域的均价中位数。group_stats df.groupby([neighbourhood_group, room_type]).agg( 房源数(price, count), 价格中位数(price, median), 价格均值(price, mean) ).round(2)结果呈现的很明显核心区房源数量最多价格中位数也最高外围区域房源数量少价格中位数明显下降。房型上整套房源的中位数价格最高共享房间最低这和直觉一致。不过要再往深看一层核心区里整套房源和独立房间的价差明显大于外围区域的同类价差。这种“位置溢价”在后续建楼时会体现为区域特征和距离特征的显著贡献。4.3 时间相关特征从评论看供需活跃度last_review、reviews_per_month、number_of_reviews是理解房源活跃度的三件套。我画了按月份统计的“最近评论数量”折线图发现整体评论活跃度有明显的季节波动旅游旺季评论量集中淡季明显下滑。这说明短租市场供需受季节影响大价格模型里加入“月份”或“是否旺季”特征会更贴近真实规律。这部分分析不复杂但能让你的结论更有业务洞察。很多人只盯着价格分布和区域箱线图忽略了时间维度结果模型少了季节性这个解释变量。4.4 相关性矩阵哪些特征和价格最相关建模型之前先算一组相关性避免把高度共线的特征直接塞进模型。我挑选了价格、坐标、评论数、可订天数、房源数、距离这些数值特征做相关性矩阵并用 seaborn 热力图展示。import seaborn as sns import matplotlib.pyplot as plt corr df[numeric_cols].corr() sns.heatmap(corr, annotTrue, cmapcoolwarm, fmt.2f) plt.show()结论通常很稳定距离与价格显著负相关越靠近中心越贵房源评分等字段若存在也与价格正相关可订天数与价格的相关性较弱。这一步给建模提供了特征筛选方向。5. 建模预测价格从线性回归到随机森林5.1 建模前处理怎么编码、选哪些特征建模前把数据集划分成特征和标签。标签选log_price而不是原始价格理由已经讲过。特征方面我保留五类数值特征latitude、longitude、distance_to_center、minimum_nights、availability_365、number_of_reviews、reviews_per_month、days_since_last_review、host_listing_count类别特征room_type、neighbourhood_group类别特征用 One-Hot 编码。实际操作时我直接用pd.get_dummies(df, columns[...])并在训练测试划分后调用避免数据泄露。5.2 基线模型线性回归和两个核心指标建模先跑一个线性回归作为基线目的是给后续复杂模型一个对比基准。划分训练集和测试集时随机种子固定为 42保证结果可复现from sklearn.model_selection import train_test_split from sklearn.linear_model import LinearRegression from sklearn.metrics import mean_squared_error, r2_score X_train, X_test, y_train, y_test train_test_split( X, y, test_size0.2, random_state42 ) lr LinearRegression() lr.fit(X_train, y_train) y_pred lr.predict(X_test) rmse mean_squared_error(y_test, y_pred, squaredFalse) r2 r2_score(y_test, y_pred)指标怎么解读RMSE代表预测值和实际值的平均偏差单位与标签一致。因为标签是log_priceRMSE 越小说明在对数尺度下预测越准确。R²是模型解释的方差比例0.4 左右在真实房价数据里已经算可用别期待像教程数据那样动不动 0.9。我当时线性回归的 R² 只有 0.4 出头RMSE 在 0.65 左右说明还有提升空间。注意把预测结果的 RMSE 读回业务层面时先做np.expm1还原价格再计算百分比误差这样更容易跟业务方解释。5.3 进阶模型随机森林的参数设置线性回归无法捕捉房型和位置之间的非线性关系所以我第二个模型选了随机森林。这个模型对缺失值不敏感、不需要特征标准化而且能输出特征重要性解释性也不错。参数设置上我用的是一组经过尝试后的稳健组合from sklearn.ensemble import RandomForestRegressor rf RandomForestRegressor( n_estimators500, max_depth15, min_samples_split5, min_samples_leaf2, random_state42, n_jobs-1, oob_scoreTrue ) rf.fit(X_train, y_train)参数为什么这样设n_estimators500保证预测稳定继续增大到 1000 的边际收益很小max_depth15限制树深防止训练集样本量不大时过拟合min_samples_split5和min_samples_leaf2相当于正则化让每棵树不那么“钻牛角尖”。oob_scoreTrue可以免费看到一个袋外评分作为快速验证。最终随机森林的 R² 提升到 0.55 左右RMSE 降到 0.55 附近。这个提升说明确实存在非线性关系。特征数量不多训练耗时可接受。5.4 结果解读真正影响价格的因素随机森林有一个特性就是训练完成后可以直接看feature_importances_。我当时按重要性排序后发现排名靠前的特征基本稳定为distance_to_center、room_type、latitude、longitude、minimum_nights、number_of_reviews。这个结果的意义不在于“模型能用”而在于它能回答业务问题位置仍然是短租定价最核心的因素距离核心圈越近价格越高房型的影响紧随其后整套房源的溢价明显评论数反映房源口碑和人气也会正向影响价格。线性回归的系数还能告诉你方向随机森林只能给重要程度所以我更推荐线性回归和树模型一起跑一个用来说明方向和强度一个用来做预测精度。两种视角互补。6. 可视化与交付让分析结果能被听懂6.1 三张必画图地图、箱线图、特征重要性交付给非技术听众时图的数量不是越多越好而是每张图都要回答一个问题。我最终选了这三张第一张是价格空间分布图。用经纬度做散点图颜色映射到价格立刻可以看到核心区颜色偏亮、外围偏暗比任何文字都直观plt.scatter(df[longitude], df[latitude], cdf[price], cmapplasma, s4, alpha0.5) plt.colorbar(labelprice) plt.show()第二张是区域与房型的箱线图用来展示“不同区域不同房型”的价格分布既能看中位数也能看波动范围。第三张是特征重要性条形图直接展示模型认为哪些变量最重要。importance pd.Series(rf.feature_importances_, indexX_train.columns).sort_values(ascendingTrue) importance.plot.barh(figsize(8, 8)) plt.show()6.2 输出结构化结论一行结论配一张图我在项目收尾时按照“结论 → 证据 → 建议”的结构整理了一页纸报告。比如结论位置是短租定价的最强影响因素。证据价格散点图呈现明显的中心向外围递减距离变量在模型重要性中排第一。建议如果想提高收益核心区小户型比外围大户型更有竞争力。这个方法很适合工作场景。别把 20 页图表全丢给老板一个核心结论配一张核心图是最有效的表达方式。6.3 如何把项目代码改造成可复用模板做完一版分析后我把清洗、特征工程、建模、画图分别封装成函数文件名按流程命名。这样下次拿到另一个城市的开放数据只需要替换数据源路径微调字段映射就能复用同一套流程。我建议你也这么做把load_data()、clean_data()、add_features()、train_model()独立出来固定输入输出格式。第一次写可能多花半小时但后续迭代和换数据集时省下的时间远不止半小时。7. 常见问题与排查技巧实录7.1 数据加载失败与乱码怎么处理我在加载 CSV 时遇到过两种典型问题一是文件路径含中文或空格导致读取失败二是文件编码不是默认的 UTF-8。读入时最好显式指定编码df pd.read_csv(listings.csv, encodingutf-8)如果报错换成encodinglatin-1或encodinggbk试试。另外尽量避免在路径中使用中文目录这是最简单的避坑方式。7.2 缺失值比例超过一半的列怎么处理有些字段缺失比例可能超过 60%比如评论相关列。这时候要区分两种情形如果缺失集中在某个区域或某个房型那可能是数据登记问题如果是随机缺失需要判断该列的业务价值。我一般原则是重要特征缺失率超过 60%先不要直接删列而是构造“是否缺失”特征再做模型对比。这样能判断缺失本身是否包含信息。随意删列会丢失这部分信号。7.3 模型和测试集分不好导致过拟合怎么办我当时踩过的坑是先对整个数据集做了 One-Hot 编码再切分训练测试集结果特征里包含了测试集的信息属于“数据泄露”。虽然随机森林的 R² 高达 0.7但换到新数据立刻掉下来。正确做法是先切分再在训练集上做编码和特征计算。更严谨一点连续特征如果要做标准化也应该先用训练集的均值方差去转换测试集而不是各自独立处理。7.4 关于这个项目的几点个人实操心得这个项目我前后完整跑了三轮。第一轮只想快点出结果忽略了不少业务细节第二轮补了距离特征和日期处理模型解释性变好很多第三轮才开始整理函数和报告也算找到了比较舒适的节奏。最后再分享一个小技巧做这类全流程项目时从一开始就给列名用英文、给代码文件按数字编号你会发现在最后写报告、复现结果时会顺畅很多。真实项目里没人看你写了多花哨的代码只看你能不能稳定复现结果、把结论讲清楚。数据分析项目1到这里收尾下一期我会把同样的流程换一份数据再做一遍对比两次分析里哪些步骤可以完全复用哪些环节必须重新思考。
RELATED

相关推荐

SQL聚合查询从入门到实战:GROUP BY、HAVING与JOIN的常见陷阱与优化

SQL聚合查询从入门到实战:GROUP BY、HAVING与JOIN的常见陷阱与优化

说实话,写了那么多年代码、刷了那么多套面试题,我越来越觉得SQL里最容易被低估的就是聚合。很多人觉得聚合不就是 SUM、COUNT、GROUP BY 嘛,闭着眼都会写。但真到了线上,一个 COUNT 翻倍、一个 WHERE 和 HAVING 用错,分…

📅 2026/10/13 4:22:15
C++游戏开发中enum class实战:从传统enum坑到类型安全迁移

C++游戏开发中enum class实战:从传统enum坑到类型安全迁移

做游戏客户端这几年,C枚举是几乎每个系统都会用到的基础设施:角色状态、怪物AI、技能类型、消息通道、资源分类,随手一数就是一大串。以前项目里到处是C风格的enum,写起来确实爽——不用敲那么多字,还自动兼容整数。可…

📅 2026/10/13 4:17:14
Android纵向滑动页面实战:三容器选型与避坑指南

Android纵向滑动页面实战:三容器选型与避坑指南

简介:这是一份面向Android初中级开发者的纵向滑动页面实现资源,围绕ViewPager详细讲解如何构建上下滑动、翻页并显示页码的交互效果。压缩包内共61个文件,主要包括Java源码、XML布局与资源文件、编译生成的class与dex、android-support-v4.ja…

📅 2026/10/13 4:17:14
MORE NEWS

更多资讯

📰

STM32 CAN总线实战:从协议原理到配置收发

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

📰

多模态Agent如何规划UI测试路径:从感知融合到动态决策的工程实践

1. 多模态 Agent 做 UI 测试,到底难在哪UI 测试这件事,做过的人都懂——写起来不难,维护起来要命。一个按钮挪了位置、一个弹窗改了文案、一个加载动画多转了半秒,传统基于选择器的自动化脚本就可能集体飘红。而多模态 Agent 的出…

📰

多步任务总在细节崩盘?用技能编排让智能体真正稳定

最初让我意识到"工具调用"和"技能编排"是两码事的,是一次很普通的实测:我在一个demo里给智能体接入了邮件发送、日历查询和文档搜索三个工具,模型只凭从三个工具拿到的零散结果,接连搞砸了一个"帮用户确…

📰

Agent技能系统实战:为大模型装上可插拔的“手”和“脚”

这两年但凡碰过AI应用开发的,应该都绕不开一个词——Agent(智能体)。模型本身只是“脑子”,真正让它干活的,是那一套技能系统,也就是项目标题里说的“agent-skills”。不少团队早期做Agent产品时都有一个共…

📰

AnyPS5:跨平台文件处理与格式转换的轻量化解决方案

1. 项目缘起与核心定位AnyPS5 这个名字第一次出现在我视野里的时候,我正被一堆跨平台文件处理的需求折腾得够呛。团队里有人用 Windows 做设计,有人用 macOS 写代码,还有人习惯在 Linux 环境下跑批处理脚本,每次交付物在三个系统之…

📰

UCINET数据导入实战:格式规范、Excel整理与高频排错

1. 先搞清楚UCINET到底在等什么数据很多人在UCINET上栽的第一个跟头,不是不会跑算法,而是数据根本喂不进去。明明Excel里填得工工整整,一点Import却报错,或者导进去之后变成一团乱麻,节点对不上、值全错位。这些问题的…

TODAY

今日更新

THIS WEEK

本周精选

THIS MONTH

本月热门

读完文章,想聊聊您的网站?

告诉我们您的行业与需求,资深顾问一对一梳理方案与报价,全程免费。

📞 💬