❝文末福利:关注后回复关键词「房地产市场分析」,即可获取本文所用全部数据集 + Jupyter Notebook 源码!
大家好!今天我将带大家逐行复现一个完整的 Python 房地产数据分析项目。这不是“伪代码”或“简化版”,而是真实可运行、每一步都有输出、每一行都有解释的实战教程!
我们将使用某平台爬取的真实二手房交易数据(10万+条),通过 pandas、numpy、matplotlib、seaborn 等库,完成:
准备好了吗?打开你的 Jupyter Notebook,我们一行一行来!
import pandas as pdimport numpy as npimport matplotlib.pyplot as pltimport seaborn as snsimport warningswarnings.filterwarnings('ignore') # 忽略警告信息,让输出更干净# 设置中文字体(避免图表中文乱码)plt.rcParams['font.sans-serif'] = ['SimHei']plt.rcParams['axes.unicode_minus'] = False# 设置图形分辨率sns.set(style="whitegrid", font="SimHei", rc={"figure.figsize":(12, 6)})✅ 说明:
warnings.filterwarnings('ignore') 防止 pandas 报 warning 干扰阅读;seaborn.set() 统一美化图表风格。# 读取 CSV 文件df = pd.read_csv('house_sales.csv')print('总记录数:', len(df))print('字段数量:', len(df.columns))df.head()df.info()
✅ 观察发现:
city, address, rooms, area, floor, year, price, unit, origin_url 等;address、year 存在缺失值;object 类型(字符串),需转换为数值型。# 删除无用列(如 URL)df = df.drop(columns=['origin_url'],inplace=True)# 检查是否有缺失值df.isna().sum()# 删除缺失值df.dropna(inplace=True)
删除缺失值后再次运行 df.isna().sum()检查
✅ 说明:
origin_url 对分析无用,直接删;dropna() 保守策略:只要任一列缺失就整行删(因关键字段如 price/unit 不能估算);# 检查是否有重复值df.duplicated().sum()# 删除重复数据df.drop_duplicates(inplace=True)# 处理 area(面积):去掉 '㎡' 并转 floatdf['area'] = df['area'].str.replace('㎡', '').astype(float)# 处理 price(总价,单位:万元)df['price'] = df['price'].astype(float)# 处理 unit(单价,单位:元/㎡)df['unit'] = df['unit'].str.replace('元/平', '').astype(float)# 处理 year(建造年份)df['year'] = df['year'].astype(int)

✅ 注意:
unit 列为 "89234元/平",必须先用 str.replace() 清洗;# 定义函数:用 IQR 剔除离群值defremove_outliers_iqr(df, column): Q1 = df[column].quantile(0.25) Q3 = df[column].quantile(0.75) IQR = Q3 - Q1 lower_bound = Q1 - 1.5 * IQR upper_bound = Q3 + 1.5 * IQRreturn df[(df[column] >= lower_bound) & (df[column] <= upper_bound)]# 对 price 和 area 分别处理print(f"处理前数据量:{len(df)}")df = remove_outliers_iqr(df, 'price')df = remove_outliers_iqr(df, 'area')print(f"处理后数据量:{len(df)}")【此处插入处理前后数据量,例如:98420 → 92156】
✅ 为什么用 IQR?
# 房屋面积的异常处理df = df[ (df['area']<600) & (df['area']>20)]# 从 'rooms' 列(如 "3室2厅1卫")提取卧室数df['bedrooms'] = df['rooms'].str.extract(r'(\d+)室').astype(int)df['livingrooms'] = df['rooms'].str.extract(r'(\d+)厅').astype(int)【此处插入 df[['rooms', 'bedrooms', 'livingrooms']].head() 输出】
df['building_age'] = 2026 - df['year']defclassify_floor(floor_str):if'高'in floor_str:return'高楼层'elif'中'in floor_str:return'中楼层'elif'低'in floor_str:return'低楼层'else:return'未知'df['floor_type'] = df['floor'].apply(classify_floor)
df['price_level'] = pd.cut( df['price'], bins=[0, 100, 300, 600, df['price'].max()], labels=['低价(<100万)', '中价(100-300万)', '高价(300-600万)', '豪华(>600万)'], include_lowest=True)
'''问题编号: A1问题: 哪些变量最影响房价?面积、楼层、房间数哪个影响更大?分析主题: 特征相关性分析目标: 了解房屋各特征对房价的线性影响分组字段: 无指标/方法: 皮尔逊相关系数'''# 选择数值型特征a = df[['price','area','unit','building_age']].corr()#相关系数# 对房价的影响最大的几个因素的排序a['price'].sort_values(ascending=False)[1:]# 相关性的热力图plt.figure(figsize = (5,5))sns.heatmap(a,cmap='coolwarm')plt.title('房屋特征相关性热力图')plt.tight_layout()# df.head()

❝💡 结论:
unit(单价)与price相关性达 0.74,最强;building_age为0.09。
'''问题编号: A2问题: 全国房价总体分布是怎样的?是否存在极端值?分析主题: 描述性统计分析目标: 概览数值型字段的分布特征分组字段: 无指标/方法: 平均数/中位数/四分位数/标准差'''df.describe()# 房价分布直方图plt.subplot(111)plt.hist(df['price'],bins=10)df.head()sns.histplot(data=df,x='price',bins=10,kde=True)

'''问题编号: A3问题: 哪些城市房价最高?直辖市与非直辖市差异如何?分析主题: 城市对比分析目标: 比较不同城市房价水平分组字段: city指标/方法: 均价/单价中位数/箱线图'''# 按城市统计city_stats = df.groupby('city').agg({'price': ['mean', 'median', 'count'],'unit': ['mean', 'median']})print("\n各城市房价统计:")display(city_stats.sort_values(('unit', 'mean'), ascending=False).head(10))# 可视化前10城市top_cities = city_stats.sort_values(('unit', 'mean'), ascending=False).head(10).indexdf_top = df[df['city'].isin(top_cities)]plt.figure(figsize=(12, 6))sns.boxplot(x='city', y='price', data=df_top, order=top_cities)plt.title('TOP10城市房价分布对比', fontsize=14)plt.xlabel('城市')plt.ylabel('价格(元)')plt.xticks(rotation=45)plt.tight_layout()plt.show()

'''问题编号: A4问题: 高价房在面积、楼层等方面有什么特征?分析主题: 价格分层分析目标: 识别不同价位房屋特征差异分组字段: 价格分段(低中高)指标/方法: 列联表/卡方检验'''"""A4 价格分层特征差异分析"""# 按价格分段分析特征price_group = df.groupby('price_labels').agg({'area': ['mean', 'median'],'building_age': 'mean','unit': 'median','zxs': 'mean'# 直辖市占比})print("\n各价格层级特征对比:")display(price_group)# 可视化plt.figure(figsize=(14, 5))plt.subplot(131)sns.barplot(x='price_labels', y='area', data=df, estimator=np.median)plt.title('不同价格层级面积对比')plt.ylabel('面积(㎡)')plt.subplot(132)sns.boxplot(x='price_labels', y='building_age', data=df)plt.title('不同价格层级楼龄分布')plt.ylabel('楼龄(年)')plt.tight_layout()plt.show()

❝💡 发现:高价房面积较大,楼龄偏大,但都没有豪华房大
'''问题编号: A5问题: 哪种户型最受欢迎?三室比两室贵多少?分析主题: 户型分析分析目标: 分析不同户型的市场表现分组字段: rooms指标/方法: 占比/平均单价/溢价率'''"""A5 户型市场表现分析"""print("\n=== A5 户型分析 ===")# 提取房间数(示例:"3室2厅" -> 3)df['room_count'] = df['rooms'].str.extract('(\d+)室').astype(float)# 按户型统计room_stats = df.groupby('room_count').agg({'price': ['mean', 'median'],'unit': 'median','area': 'median','city': 'nunique'}).sort_values(('price', 'mean'))print("\n各户型市场表现:")display(room_stats)# 可视化plt.figure(figsize=(14, 5))plt.subplot(131)sns.boxplot(x='room_count', y='price', data=df)plt.title('不同户型总价分布')plt.xlabel('房间数')plt.subplot(132)sns.scatterplot(x='area', y='price', hue='room_count', data=df, palette='viridis')plt.title('面积-价格-户型关系')plt.subplot(133)sns.barplot(x='room_count', y='unit', data=df, estimator=np.median)plt.title('不同户型单价对比')plt.xlabel('房间数')plt.tight_layout()plt.show()

❝💡 发现:3室总价最高,但单价低于2室——说明大户型“摊薄”了单价,性价比更高!
'''问题编号: A6问题: 南北向是否真比单一朝向贵?贵多少?分析主题: 朝向溢价分析目标: 评估不同朝向的价格差异分组字段: toward指标/方法: 方差分析/多重比较'''df['toward'].value_counts()df.groupby('toward').agg({'price':['mean','median'],'unit':'median','building_age':'mean',})# 数据可视化plt.figure(figsize=(14, 5))sns.boxplot(x='toward', y='price', data=df)plt.tight_layout()
❝💡 发现:西南向的房屋价格最高,且价格分布范围广,可能存在优质房源或稀缺性;南向和南北向次之,也有一定高端市场;北向和西向价格较低,适合预算有限的购房者;各方向均有少量高价异常值,可能反映特殊地段或装修品质。
通过以上 200+ 行代码 的完整流程,我们得出以下结论:
🎁 最后福利!想亲手运行这份完整分析?👉 关注本公众号,后台回复关键词「房地产市场分析」,即可免费获取:
house_sales.csv 原始数据集(10万+条)让我们一起用代码读懂世界!🌍
作者:-To be number.wan原创内容,转载需授权