波士顿房价数据集深度剖析:13个特征里谁在真正影响房价?(附完整EDA代码)

波士顿房价数据集的十三面棱镜:从数据清洗到模型实战的深度解析

每次打开波士顿房价数据集,我都有种面对一个经典谜题的感觉。这个看似简单的数据集,包含了506个样本和13个特征,却成为了机器学习入门者必须跨越的一道门槛。但真正深入其中,你会发现它远不止是一个教学工具——它是一面多棱镜,折射出数据科学从探索到建模的完整思考过程。对于数据分析师和房地产从业者来说,理解这些特征背后的现实含义,远比记住几个模型参数重要得多。

今天,我想带你一起重新审视这个经典数据集,不只是跑一遍代码,而是真正理解每个特征如何影响房价,以及如何构建一个既专业又实用的分析流程。我们会从最基础的数据探索开始,一步步深入到特征工程和模型选择,最后还会讨论如何将这种分析方法应用到实际的房地产评估场景中。

1. 数据初探:理解每个特征的真实含义

在开始任何分析之前,我们必须先理解数据在说什么。波士顿房价数据集中的13个特征,每个都对应着现实世界中的某个社会经济指标。但很多人只是机械地使用这些特征,却忽略了它们背后的实际意义。

CRIM - 城镇人均犯罪率。这个指标直接影响居民的安全感,进而影响房价。但有趣的是,犯罪率与房价的关系并非简单的线性负相关。在某些区域,即使犯罪率较高,如果其他条件(如教育资源、交通便利性)足够优越,房价仍可能保持在一定水平。

ZN - 住宅用地比例(大于25,000平方英尺的地块)。这个特征反映了区域的开发密度和住宅类型。高ZN值通常意味着更多独立住宅,而低值则可能表示公寓或密集住宅区。

INDUS - 非零售业务用地比例。这个指标衡量的是区域的工业化程度。工业区附近的住宅通常价格较低,因为存在噪音、污染等问题。

CHAS - 查尔斯河虚拟变量。这是一个二值特征(1表示临河,0表示不临河)。水景房在任何城市都是稀缺资源,这个简单的0/1变量往往能带来显著的价格溢价。

NOX - 氮氧化物浓度。空气质量指标,直接关系到居住健康。在现代城市中,这个指标的重要性日益凸显。

RM - 每户平均房间数。这是最直观的房屋特征之一,但需要小心解读——房间数多不一定意味着居住舒适,还要考虑房间大小和布局。

AGE - 1940年前建造的房屋比例。这个特征反映了区域的老化程度。老社区可能有历史价值,但也可能面临设施陈旧的问题。

DIS - 到就业中心的加权距离。通勤时间是现代城市居民最关心的因素之一,这个距离指标直接影响房屋的吸引力。

RAD - 高速公路可达性指数。交通便利性对房价的影响是复杂的——太近可能有噪音问题,太远则不便。

TAX - 财产税率。税率直接影响持有成本,是投资决策的重要考虑因素。

PTRATIO - 师生比。教育资源的直接体现,对于有孩子的家庭来说是关键决策因素。

B - 黑人比例系数。这个特征需要特别谨慎对待,因为它涉及种族因素。在分析中,我们更关注其反映的社会经济结构信息。

LSTAT - 低收入人群比例。这个指标往往与房价有最强的相关性,因为它综合反映了区域的经济状况和社会阶层构成。

理解这些特征后,我们开始数据清洗的第一步——检查数据质量。

import pandas as pd
import numpy as np
from sklearn.datasets import load_boston

# 加载数据
boston = load_boston()
df = pd.DataFrame(boston.data, columns=boston.feature_names)
df['PRICE'] = boston.target

# 基础信息检查
print("数据集形状:", df.shape)
print("\n数据类型:")
print(df.dtypes)
print("\n缺失值统计:")
print(df.isnull().sum())
print("\n描述性统计:")
print(df.describe().round(2))

运行这段代码,你会立即发现几个关键信息:数据集没有缺失值,所有特征都是数值型,但数值范围差异很大。比如,CRIM的范围是0.006到88.976,而CHAS只有0和1两种值。这种量纲差异会在后续分析中带来问题,我们需要进行标准化处理。

注意:虽然波士顿房价数据集是经典数据集,但需要注意它发布于1978年,反映的是当时波士顿的房地产市场情况。在实际应用中,应该使用更新的数据,并考虑通货膨胀等因素对价格的影响。

2. 可视化探索:发现特征间的隐藏关系

数据可视化不是为了让报告好看,而是为了发现那些数字表格中难以察觉的模式。对于波士顿房价数据集,我习惯从三个层次进行可视化探索:单变量分布、双变量关系和相关性网络。

2.1 单变量分布分析

每个特征的分布形态都讲述着一个故事。让我们先看看房价本身的分布:

import matplotlib.pyplot as plt
import seaborn as sns

plt.figure(figsize=(12, 5))

# 房价分布直方图
plt.subplot(1, 2, 1)
sns.histplot(df['PRICE'], bins=30, kde=True)
plt.title('房价分布直方图')
plt.xlabel('房价(千美元)')
plt.ylabel('频数')

# 房价箱线图
plt.subplot(1, 2, 2)
sns.boxplot(y=df['PRICE'])
plt.title('房价箱线图')
plt.ylabel('房价(千美元)')

plt.tight_layout()
plt.show()

从分布图中,我们可以看到房价大致呈正态分布,但右侧有轻微拖尾,说明存在一些高价房产。箱线图显示有几个可能的离群值,但需要谨慎处理——这些"离群值"可能代表真实的豪宅,而非数据错误。

接下来,我们看看关键特征的分布情况。我特别关注LSTAT和RM,因为经验告诉我这两个特征往往最重要:

fig, axes = plt.subplots(2, 3, figsize=(15, 10))

# LSTAT分布
sns.histplot(df['LSTAT'], bins=30, kde=True, ax=axes[0, 0])
axes[0, 0].set_title('低收入人群比例(LSTAT)分布')
axes[0, 0].set_xlabel('LSTAT (%)')

# RM分布
sns.histplot(df['RM'], bins=30, kde=True, ax=axes[0, 1])
axes[0, 1].set_title('平均房间数(RM)分布')
axes[0, 1].set_xlabel('房间数')

# 犯罪率分布(取对数后)
sns.histplot(np.log1p(df['CRIM']), bins=30, kde=True, ax=axes[0, 2])
axes[0, 2].set_title('犯罪率对数分布')
axes[0, 2].set_xlabel('log(CRIM+1)')

# PTRATIO分布
sns.histplot(df['PTRATIO'], bins=30, kde=True, ax=axes[1, 0])
axes[1, 0].set_title('师生比(PTRATIO)分布')
axes[1, 0].set_xlabel('PTRATIO')

# NOX分布
sns.histplot(df['NOX'], bins=30, kde=True, ax=axes[1, 1])
axes[1, 1].set_title('氮氧化物浓度(NOX)分布')
axes[1, 1].set_xlabel('NOX浓度')

# TAX分布
sns.histplot(df['TAX'], bins=30, kde=True, ax=axes[1, 2])
axes[1, 2].set_title('财产税率(TAX)分布')
axes[1, 2].set_xlabel('TAX')

plt.tight_layout()
plt.show()

这些分布图揭示了几个重要发现:

  • LSTAT呈右偏分布,大多数区域低收入人群比例较低,但少数区域比例很高
  • RM接近正态分布,平均房间数集中在6左右
  • 犯罪率严重右偏,取对数后分布更合理
  • 师生比在不同区域差异明显

2.2 特征与房价的关系散点图

散点图能直观展示特征与房价的关系。让我们重点关注几个关键特征:

fig, axes = plt.subplots(2, 3, figsize=(15, 10))

# LSTAT vs PRICE
sns.scatterplot(x='LSTAT', y='PRICE', data=df, alpha=0.6, ax=axes[0, 0])
axes[0, 0].set_title('低收入比例 vs 房价')
axes[0, 0].set_xlabel('LSTAT (%)')
axes[0, 0].set_ylabel('房价(千美元)')

# RM vs PRICE
sns.scatterplot(x='RM', y='PRICE', data=df, alpha=0.6, ax=axes[0, 1])
axes[0, 1].set_title('房间数 vs 房价')
axes[0, 1].set_xlabel('平均房间数')
axes[0, 1].set_ylabel('房价(千美元)')

# PTRATIO vs PRICE
sns.scatterplot(x='PTRATIO', y='PRICE', data=df, alpha=0.6, ax=axes[0, 2])
axes[0, 2].set_title('师生比 vs 房价')
axes[0, 2].set_xlabel('PTRATIO')
axes[0, 2].set_ylabel('房价(千美元)')

# NOX vs PRICE
sns.scatterplot(x='NOX', y='PRICE', data=df, alpha=0.6, ax=axes[1, 0])
axes[1, 0].set_title('氮氧化物浓度 vs 房价')
axes[1, 0].set_xlabel('NOX浓度')
axes[1, 0].set_ylabel('房价(千美元)')

# DIS vs PRICE
sns.scatterplot(x='DIS', y='PRICE', data=df, alpha=0.6, ax=axes[1, 1])
axes[1, 1].set_title('就业中心距离 vs 房价')
axes[1, 1].set_xlabel('加权距离')
axes[1, 1].set_ylabel('房价(千美元)')

# CRIM vs PRICE(取对数)
sns.scatterplot(x=np.log1p(df['CRIM']), y='PRICE', data=df, alpha=0.6, ax=axes[1, 2])
axes[1, 2].set_title('犯罪率(对数) vs 房价')
axes[1, 2].set_xlabel('log(CRIM+1)')
axes[1, 2].set_ylabel('房价(千美元)')

plt.tight_layout()
plt.show()
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值