news 2026/10/3 8:52:27

Python二手房数据分析源码:从CSV清洗到可视化全流程

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Python二手房数据分析源码:从CSV清洗到可视化全流程

简介:这份资源是面向高校学生与Python初学者的一套二手房数据分析完整项目,可直接用于毕业设计、期末大作业或课程设计场景。项目以Python为核心,围绕二手房数据的采集、清洗与可视化分析展开,包含从原始数据到清洗后数据的多版本CSV文件,便于对照理解数据预处理流程。压缩包共157个文件,涵盖18个py源码、18个csv数据集、15个html页面、11个js脚本以及65张png图表,另附docx文档说明与pptx演示资料,整体约48.05MB,代码注释齐全,新手也能看懂。目前已有127人学习下载。项目经过严格调试,部署简单,下载后即可运行,界面美观、功能完善,能帮助读者快速掌握数据分析项目的完整实现思路,并直接作为高分作业提交使用。

1. 从一份二手房 CSV 说起:这套 Python 分析源码到底能干什么

如果你手头正好有一份ershoufang-origin-utf8.csv这样的二手房原始数据,打开一看字段乱、编码杂、价格带「万」字、楼层写「中楼层(共6层)」,想做个能交差的课程设计却不知道从哪下手,那这套基于 Python 的二手房数据分析源码就是冲这个场景来的。它把从原始 CSV 到清洗、统计、可视化、结论输出的整条链路都写好了,还配了文档说明和 PPT 资料,代码里带注释,新手照着跑也能看懂每一步在干嘛。适合谁?期末大作业、课程设计、毕业设计这类需要「完整可运行 + 有分析结论 + 能讲清楚」的场合。它不追求算法多前沿,追求的是流程完整、结果能复现、答辩时讲得出逻辑。下面我按自己拆包的习惯,把这份资源从数据到结论走一遍,顺带把几个容易翻车的地方标出来。

2. 数据文件与编码:先搞清楚你拿到的是哪一版 CSV

2.1 原始数据、清洗数据、编码版本三者的关系

这套资源里 CSV 文件不少,名字里带origin、clean、utf8、ansi、v1.1这些标记,很多人第一眼会懵。我先把它们的关系理清楚,不然后面读进来一堆乱码还以为是代码问题。

从文件名能看出两条线:一条是数据加工阶段,origin是原始抓取或导出的数据,clean是清洗后的;另一条是字符编码,utf8和ansi是同一份数据的不同编码版本。v1.1是清洗规则的版本号,说明清洗逻辑迭代过一次。ershoufang - 20000.csv从命名看是两万条量级的样本,ershoufang.csv则像是主数据文件。

为什么同一份数据要存两种编码?因为 Windows 上 Excel 默认按 ANSI(简体中文环境是 GBK)打开 CSV,你给它一个 UTF-8 文件,中文列名和小区名直接变乱码。反过来,有些 Python 读取脚本如果没指定编码,在 Windows 上默认走的也是本地编码。所以作者把两种编码都留了一份,本质是让你在不同工具链下都能少踩一个坑。

文件名阶段编码用途
ershoufang-origin-utf8.csv原始UTF-8Python 读取、跨平台
ershoufang-origin-ansi.csv原始ANSI/GBKExcel 直接打开
ershoufang-clean-utf8-v1.1.csv清洗后UTF-8建模、可视化输入
ershoufang-clean-ansi-v1.1.csv清洗后ANSI/GBK人工核对、Excel 查看
ershoufang - 20000.csv样本视文件而定快速试跑、演示
ershoufang.csv主数据视文件而定完整分析

选哪份取决于你要干什么。跑代码做分析,一律用clean-utf8-v1.1;想用 Excel 肉眼核对清洗结果,用clean-ansi-v1.1;想验证清洗脚本本身,才回头去读origin版本。

2.2 用 pandas 正确读入并确认编码

读 CSV 第一步不是急着分析,是先确认读进来的东西没坏。下面这段是我一般会先跑的探针代码。

import pandas as pd # 优先用 utf-8 读,如果报 UnicodeDecodeError 再换 gbk def load_csv(path): for enc in ("utf-8", "gbk", "gb18030"): try: df = pd.read_csv(path, encoding=enc) print(f"成功读取: {path} | 编码: {enc} | 形状: {df.shape}") return df except UnicodeDecodeError: continue raise ValueError("三种编码都读不了,检查文件是否损坏") df = load_csv("ershoufang-clean-utf8-v1.1.csv") print(df.columns.tolist()) print(df.head(3))

逻辑说明:gb18030是 GBK 的超集,放在最后兜底,能覆盖绝大多数简体中文 Windows 导出的文件。参数上encoding不指定时 pandas 在部分环境会默认 UTF-8,遇到 ANSI 文件直接抛UnicodeDecodeError,所以显式轮询更稳。读进来后先看shape和columns,如果列名出现\ufeff这种前缀,说明文件带 BOM,读取时加encoding="utf-8-sig"即可。

提示:如果df.shape的列数明显少于你预期的字段数,八成是分隔符不对,试试sep=";"或sep="\t"。

3. 清洗与特征处理:把「万」「平米」「中楼层」变成能算的数

3.1 清洗脚本在做什么:从字符串到数值的映射

二手房数据最烦的就是字段里混着单位和描述。总价写「350万」,单价写「45000元/平米」,面积写「89.5平米」,楼层写「中楼层(共6层)」,朝向写「南 北」。这些字段不处理,df.describe()一个都统计不出来。

清洗的核心就三件事:去单位、转数值、拆复合字段。下面这段是我按这套资源的清洗思路复现的,逻辑和clean-v1.1对得上。

import pandas as pd import numpy as np import re df = pd.read_csv("ershoufang-origin-utf8.csv", encoding="utf-8") # 1. 总价: "350万" -> 350.0 def parse_price(x): if pd.isna(x): return np.nan m = re.search(r"([\d.]+)", str(x)) return float(m.group(1)) if m else np.nan df["总价_万"] = df["总价"].apply(parse_price) # 2. 面积: "89.5平米" -> 89.5 df["面积_平米"] = df["面积"].apply(parse_price) # 3. 单价: 有些数据没有,用总价和面积反推 df["单价_元每平"] = df["总价_万"] * 10000 / df["面积_平米"] # 4. 楼层: "中楼层(共6层)" -> 楼层位置 + 总层数 def parse_floor(x): if pd.isna(x): return pd.Series([np.nan, np.nan]) s = str(x) pos = "中" if "低" in s: pos = "低" elif "高" in s: pos = "高" m = re.search(r"共(\d+)层", s) total = int(m.group(1)) if m else np.nan return pd.Series([pos, total]) df[["楼层位置", "总层数"]] = df["楼层"].apply(parse_floor) # 5. 丢弃关键字段缺失的行 df = df.dropna(subset=["总价_万", "面积_平米"]) df = df[df["面积_平米"] > 0] df.to_csv("ershoufang-clean-utf8-v1.1.csv", index=False, encoding="utf-8") print("清洗完成,剩余行数:", len(df))

逻辑说明:parse_price用正则只抓数字部分,兼容「350万」「350.5万」「350」几种写法。单价反推这一步很关键,因为原始数据里单价经常缺失或格式不统一,用总价乘一万除以面积得到的是「元/平米」,量纲统一后才能做分布分析。楼层拆成位置和总层数两个字段,是为了后面能算「中间楼层溢价」这类结论——只留一个「中楼层(共6层)」字符串,任何统计都做不了。

参数上,dropna的subset只卡总价和面积,其他字段缺失先留着,避免样本被砍太狠。面积_平米 > 0是防除零,也是防那种面积填 0 的脏数据。

3.2 特征工程:哪些字段值得留,哪些是噪音

清洗完不是所有列都要进分析。我一般会按「能不能量化、有没有区分度」两个标准筛一遍。

能直接量化的:总价、单价、面积、总层数、房龄(如果有建成年份)。能编码成类别的:楼层位置(低/中/高)、朝向(南/北/东南等)、装修情况、有无电梯。这些字段在可视化阶段能直接分组对比。

噪音字段通常是:房源标题、小区详细地址、经纪人姓名、挂牌时间戳(如果只做截面分析)。标题里信息量大但非结构化,除非你要做文本挖掘,否则留着只会让 DataFrame 变宽。地址如果只到小区级别,可以提取「区域」做分组,再细就没意义了。

# 从地址里提取区域,用于分组统计 df["区域"] = df["地址"].astype(str).str.extract(r"^(\w+?区)") # 朝向做简化: 只保留第一个方向 df["主朝向"] = df["朝向"].astype(str).str.split().str[0] # 房龄: 假设有建成年份字段 if "建成年份" in df.columns: df["房龄"] = 2024 - pd.to_numeric(df["建成年份"], errors="coerce")

str.extract用非贪婪匹配抓「XX区」,是因为地址格式通常是「朝阳区XX路XX号」,贪婪匹配会把后面全吞进去。errors="coerce"让转不了的年份变 NaN,而不是直接报错中断。

注意:区域提取依赖地址格式统一。如果有的地址写「朝阳区」有的写「北京市朝阳区」,正则需要调整,否则会漏掉一批。清洗后建议df["区域"].value_counts(dropna=False)看一眼缺失比例。

4. 分析与可视化:把均价、面积、区域差异讲成结论

4.1 描述性统计与分组聚合

数据洗干净后,第一步是看整体分布,第二步是按维度拆开看差异。这套资源的分析部分基本围绕「均价」「面积」「区域」「楼层」四个维度展开。

import pandas as pd df = pd.read_csv("ershoufang-clean-utf8-v1.1.csv", encoding="utf-8") # 整体均价和面积分布 print("整体均价(元/平):", df["单价_元每平"].mean().round(0)) print("面积中位数(平):", df["面积_平米"].median()) print(df[["总价_万", "单价_元每平", "面积_平米"]].describe().round(1)) # 按区域看均价 region_stat = df.groupby("区域").agg( 房源数=("单价_元每平", "count"), 均价=("单价_元每平", "mean"), 中位面积=("面积_平米", "median") ).round(0).sort_values("均价", ascending=False) print(region_stat) # 按楼层位置看均价 floor_stat = df.groupby("楼层位置")["单价_元每平"].mean().round(0) print(floor_stat)

逻辑说明:groupby后接agg可以一次算出多个指标,比循环高效。count用单价字段而不是总价,是因为单价缺失更少(前面反推过)。sort_values降序排列让均价最高的区域排前面,答辩时一眼能看出结论。

参数上,round(0)把浮点压成整数,均价精确到元就够了,小数位反而干扰阅读。如果某个区域房源数只有个位数,它的均价参考价值很低,建议加个过滤:region_stat[region_stat["房源数"] >= 30]。

4.2 可视化:三张图讲清楚一个结论

分析类项目答辩时,图比表管用。这套资源的可视化一般用 matplotlib 或 pyecharts,我按 matplotlib 给一套能直接跑的。

import matplotlib.pyplot as plt import pandas as pd df = pd.read_csv("ershoufang-clean-utf8-v1.1.csv", encoding="utf-8") plt.rcParams["font.sans-serif"] = ["SimHei"] # 中文显示 plt.rcParams["axes.unicode_minus"] = False fig, axes = plt.subplots(1, 3, figsize=(18, 5)) # 图1: 单价分布直方图 axes[0].hist(df["单价_元每平"].dropna(), bins=50, color="#4C72B0") axes[0].set_title("单价分布") axes[0].set_xlabel("元/平米") # 图2: 各区域均价条形图 region_mean = df.groupby("区域")["单价_元每平"].mean().sort_values() axes[1].barh(region_mean.index, region_mean.values, color="#55A868") axes[1].set_title("各区域均价") axes[1].set_xlabel("元/平米") # 图3: 面积与总价散点 axes[2].scatter(df["面积_平米"], df["总价_万"], alpha=0.3, s=8) axes[2].set_title("面积-总价关系") axes[2].set_xlabel("面积(平米)") axes[2].set_ylabel("总价(万)") plt.tight_layout() plt.savefig("analysis_result.png", dpi=150) plt.show()

逻辑说明:SimHei是 Windows 自带中文字体,Linux 上可能没有,换成WenQuanYi Micro Hei或Noto Sans CJK SC。axes.unicode_minus = False解决负号显示成方块的问题。直方图bins=50是经验值,数据量两万左右时分布看得比较细。散点图alpha=0.3让重叠点透出来,s=8控制点大小,不然两万个点糊成一团。

提示:如果散点图出现明显的离群点(比如面积 500 平但总价 50 万),先回清洗阶段查是不是单位解析错了,别急着在可视化里裁掉。

5. 避坑与排查:跑这套源码最容易翻车的五个地方

5.1 编码报错 UnicodeDecodeError

现象:pd.read_csv直接抛UnicodeDecodeError: 'utf-8' codec can't decode byte...。

原因:文件是 ANSI/GBK 编码,但读取时用了默认 UTF-8。

解决:按 2.2 的轮询写法,依次试utf-8、gbk、gb18030。如果文件带 BOM,用utf-8-sig。别去改文件编码,改读取参数更快。

5.2 中文列名变乱码

现象:df.columns打印出来是['\xe6\x80\xbb\xe4\xbb\xb7']这种,或者显示成问号。

原因:读取编码和文件实际编码不匹配,或者终端本身不支持中文输出。

解决:先确认读取编码正确,再确认终端编码。Windows 命令行跑chcp 65001切 UTF-8。如果是在 IDE 里跑,检查文件编码设置。

5.3 单价算出天文数字或负数

现象:单价_元每平出现几百万甚至负数。

原因:总价单位没统一。有的行写「350万」,有的写「350」,解析后一个当万一个当元,反推单价就差了 10000 倍。负数通常是面积字段混进了「-」或解析到了错误数字。

解决:在parse_price后加一步校验,df = df[(df["总价_万"] > 10) & (df["总价_万"] < 10000)],把明显不合理的总价区间卡掉。面积同理,设个10 < 面积 < 1000的合理区间。

5.4 groupby 后区域数量对不上

现象:明明有 10 个区,groupby("区域")只出来 6 个。

原因:区域提取正则没覆盖所有地址格式,部分行提取结果是 NaN,被 groupby 默认丢弃了。

解决:df["区域"].isna().sum()看缺失量,df[df["区域"].isna()]["地址"].head(20)看漏掉的格式,补正则。或者用dropna=False保留 NaN 组,先看清楚再决定怎么处理。

5.5 可视化中文显示成方块

现象:图里标题、轴标签的中文全是方框。

原因:matplotlib 默认字体不含中文。

解决:plt.rcParams["font.sans-serif"] = ["SimHei"],Linux 上换成系统里实际有的中文字体。查系统字体用fc-list :lang=zh。改完记得重启 kernel,rcParams 在部分环境不会热生效。

6. 进阶技巧:把分析结论做成能讲三分钟的答辩素材

跑通代码只是及格线,答辩时老师不会看你df.head(),他要的是「你发现了什么」。这套资源配了 PPT 资料,但 PPT 是壳,里面的结论得你自己从数据里挖。我一般会从三个角度切:区域差异、面积段分布、楼层溢价。

区域差异最好讲。按 4.1 的region_stat拿到各区域均价排序,挑最高和最低两个区对比,说清楚价差倍数。比如「均价最高的区是最低区的 2.3 倍」,这一句就是一个结论。再配一张条形图,视觉冲击直接拉满。

面积段分布适合讲刚需和改善的差异。把面积切成60 以下、60-90、90-120、120 以上四段,看每段的房源占比和均价。

bins = [0, 60, 90, 120, 1000] labels = ["60以下", "60-90", "90-120", "120以上"] df["面积段"] = pd.cut(df["面积_平米"], bins=bins, labels=labels) seg_stat = df.groupby("面积段", observed=True).agg( 房源数=("单价_元每平", "count"), 均价=("单价_元每平", "mean"), 占比=("单价_元每平", lambda x: len(x) / len(df)) ).round(2) print(seg_stat)

pd.cut做分箱,observed=True避免类别型 groupby 产生空组。占比用 lambda 算,比单独再除一次简洁。如果发现 60-90 段房源最多但均价不是最低,说明刚需盘竞争激烈但价格没被压下来,这就是一个能展开讲的点。

楼层溢价是加分项。用 3.1 拆出来的楼层位置做分组,看低/中/高楼层均价差异。如果中间楼层明显贵,可以结合「采光」「电梯」解释;如果差异不大,说明这个城市购房者对楼层不敏感,也是个结论。

最后说个我自己的习惯:每次跑完分析,我会把region_stat、seg_stat、floor_stat三个表导出成 CSV,答辩前打印出来贴在电脑边上。老师问哪个数,直接念,不用现场翻代码。这套源码的文档说明和 PPT 资料能帮你把框架搭起来,但真正让答辩稳的,是你自己跑过一遍、改过参数、知道每个数字从哪来的那份底气。从那以后我每次做数据分析类项目,都强制自己把关键统计表导出留档,不再只依赖 notebook 里的输出。希望帮到你。

本文还有配套的精品资源,点击获取

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

Mie散射理论与Python实现:从散射光强计算到粒径反演

简介&#xff1a;基于Mie理论的散射光强计算是光学与大气环境研究中的常见需求。面向需要模拟微小粒子散射行为的科研人员与高年级学生&#xff0c;这份MATLAB代码包可用于求解任意尺寸球形颗粒的散射光强、消光系数以及角度分布。压缩包为rar格式&#xff0c;共10个文件&#…

作者头像 李华
网站建设 2026/10/3 8:51:44

可乐管道疏通靠谱吗值得信赖吗

南京可乐管道工程有限公司&#xff0c;深耕南京民生维修领域15年&#xff0c;是一家主打管道疏通、防水补漏、电路维修安装、水下打捞的本土综合维修服务商&#xff0c;致力于为南京家庭用户及商业客户提供透明靠谱、极速响应的维修维保服务。 核心实力拆解 本土深耕积累的技…

作者头像 李华
网站建设 2026/10/3 8:51:12

AI设计工作流实战:从提示词工程到多AI协作的完整方法论

1. 为什么我要重构一套AI设计工作流 做设计十年&#xff0c;前五年我靠的是三件套&#xff1a;手绘板、Sketch、CtrlS。后五年多了一个东西——AI协同。说实话&#xff0c;第一次接触AI生成图像工具的时候&#xff0c;我和大多数同行一样&#xff0c;觉得这玩意儿就是“玩具”&…

作者头像 李华
网站建设 2026/10/3 8:48:56

AI如何自动识别暗标出现人员姓名是否存在废标废标风险?智能评审项目实

这里写自定义目录标题欢迎使用Ma rkdown编辑器新的改变功能快捷键合理的创建标题&#xff0c;有助于目录的生成如何改变文本的样式插入链接与图片如何插入一段漂亮的代码片生成一个适合你的列表创建一个表格设定内容居中、居左、居右SmartyPants创建一个自定义列表如何创建一个…

作者头像 李华