别再只盯着代码了!用Python+Seaborn可视化带你重新理解波士顿房价数据集
用数据讲故事:Seaborn可视化解锁波士顿房价的13个秘密
当我们拿到一份数据集时,第一反应往往是"如何建模预测"。但在这之前,数据本身已经蕴含了无数故事等待讲述。波士顿房价数据集作为机器学习入门的经典案例,常被简化为线性回归的练习题,而它真正的价值远不止于此。
1. 数据可视化:超越代码的认知工具
数据科学不仅仅是编写算法,更是理解数据的过程。可视化在这个过程中扮演着不可替代的角色:
- 直观认知:人脑处理图像信息的速度比数字快60,000倍
- 模式识别:可视化能揭示统计指标无法展现的非线性关系和异常值
- 决策支持:为后续特征工程和模型选择提供方向性指导
- 故事讲述:将抽象数据转化为可理解的商业洞察
提示:优秀的可视化应当回答业务问题,而不仅仅是展示数据
Seaborn作为基于Matplotlib的高级接口,提供了更简洁的API和更美观的默认样式。它特别适合用于探索性数据分析(EDA),让我们能够用更少的代码产生更具信息量的可视化结果。
2. 数据初探:从整体到细节
加载数据后,我们首先需要建立对数据集的基本认知:
import seaborn as sns
import matplotlib.pyplot as plt
from sklearn.datasets import fetch_openml
# 加载数据
boston = fetch_openml(name='boston', version=1, as_frame=True)
df = pd.DataFrame(boston.data, columns=boston.feature_names)
df['PRICE'] = boston.target
# 基本信息查看
print(f"数据集形状: {df.shape}")
print(f"特征列表: {list(df.columns)}")
波士顿房价数据集包含506个样本和14个字段(13个特征+目标变量PRICE)。这些特征涵盖了房屋本身属性(如房间数RM)、社区环境(如犯罪率CRIM)和区位因素(如到就业中心的距离DIS)。
2.1 目标变量分布分析
房价的分布情况直接影响我们的建模策略:
plt.figure(figsize=(10, 6))
sns.histplot(df['PRICE'], bins=30, kde=True, color='royalblue')
plt.title('波士顿房价分布', fontsize=14)
plt.xlabel('价格(千美元)')
plt.ylabel('频数')
plt.show()
从分布图中我们可以观察到:
- 价格集中在20-25千美元区间
- 存在右偏(少数高价值房产)
- 可能的异常值(价格>50的极少数样本)
2.2 数值特征统计概览
使用Seaborn的pairplot可以快速查看多个特征的分布和关系:
# 选择部分关键特征进行可视化
key_features = ['RM', 'LSTAT', 'PTRATIO', 'PRICE']
sns.pairplot(df[key_features], diag_kind='kde', plot_kws={'alpha':0.6})
plt.suptitle('关键特征分布与关系矩阵', y=1.02)
plt.show()
这种矩阵式可视化能同时展现:
- 对角线上的单变量分布
- 非对角线上的双变量散点关系
- 初步判断线性/非线性关系
3. 特征关系深度挖掘
3.1 相关性热力图:全局视角
相关系数矩阵是理解特征间关系的起点:
plt.figure(figsize=(12, 8))
corr = df.corr()
mask = np.triu(np.ones_like(corr, dtype=bool)) # 创建上三角掩码
sns.heatmap(corr, mask=mask, annot=True, fmt='.2f', cmap='coolwarm',
cbar=True, vmin=-1, vmax=1, linewidths=0.5)
plt.title('特征相关性热力图', fontsize=14)
plt.xticks(rotation=45)
plt.yticks(rotation=0)
plt.show()
从热力图中我们可以提取几个关键发现:
| 特征组合 | 相关系数 | 业务含义 |
|---|---|---|
| RM-PRICE | 0.70 | 房间数越多,房价越高 |
| LSTAT-PRICE | -0.74 | 低收入人群比例越高,房价越低 |
| PTRATIO-PRICE | -0.51 | 学生/教师比越高,房价越低 |
| NOX-DIS | -0.77 | 远离就业中心,氮氧化物浓度降低 |
3.2 关键特征与房价的微观关系
热力图展示了整体相关性,而散点图能揭示更细致的关系模式:
fig, axes = plt.subplots(1, 3, figsize=(18, 5))
# 房间数与房价
sns.regplot(x='RM', y='PRICE', data=df, ax=axes[0],
scatter_kws={'alpha':0.5}, line_kws={'color':'red'})
axes[0].set_title('房间数与房价关系')
# 低收入比例与房价
sns.regplot(x='LSTAT', y='PRICE', data=df, ax=axes[1],
scatter_kws={'alpha':0.5}, line_kws={'color':'red'})
axes[1].set_title('低收入比例与房价关系')
# 学生教师比与房价
sns.regplot(x='PTRATIO', y='PRICE', data=df, ax=axes[2],
scatter_kws={'alpha':0.5}, line_kws={'color':'red'})
axes[2].set_title('学生教师比与房价关系')
plt.tight_layout()
plt.show()
这些可视化揭示了有趣的现象:
- RM与PRICE呈现明显的线性正相关
- LSTAT与PRICE显示出可能的非线性关系(曲线趋势)
- PTRATIO与PRICE的关系中存在明显的离群点
3.3 分类特征的探索:以CHAS为例
CHAS(查尔斯河边界)是数据集中唯一的二元分类变量:
plt.figure(figsize=(8, 5))
sns.boxplot(x='CHAS', y='PRICE', data=df, palette='Set2')
plt.title('查尔斯河边界对房价的影响')
plt.xticks([0,1], ['不临河', '临河'])
plt.xlabel('')
plt.ylabel('价格(千美元)')
plt.show()
箱线图清晰展示了:
- 临河房产的中位数价格更高
- 价格分布范围更广(可能存在高端临河房产)
- 非临河房产中有更多低价异常值
4. 高级可视化技巧
4.1 条件分布分析:房价的多维度视角
使用FacetGrid可以同时考察多个条件的影响:
# 将RM离散化为三个等级
df['RM_LEVEL'] = pd.cut(df['RM'], bins=3, labels=['低', '中', '高'])
g = sns.FacetGrid(df, col='RM_LEVEL', row='CHAS', height=4, aspect=1.2)
g.map_dataframe(sns.histplot, x='PRICE', bins=15, kde=True)
g.set_axis_labels('价格(千美元)', '频数')
g.fig.suptitle('不同房间数和临河状态的房价分布', y=1.05)
plt.show()
这种分面可视化揭示了:
- 房间数多的房产,无论是否临河,价格分布都向右偏移
- 临河且房间数多的房产价格分布最集中
- 房间数少的临河房产反而价格波动更大
4.2 交互关系可视化
某些特征对房价的影响可能不是独立的,而是相互作用的:
plt.figure(figsize=(10, 6))
sns.lmplot(x='LSTAT', y='PRICE', hue='RM_LEVEL', data=df,
height=6, aspect=1.2, scatter_kws={'alpha':0.4})
plt.title('低收入比例与房价关系(按房间数分层)')
plt.xlabel('低收入人群比例(%)')
plt.ylabel('价格(千美元)')
plt.show()
这个可视化表明:
- 在低收入比例相同的情况下,房间数多的房产价格更高
- 房间数少的房产对LSTAT变化更敏感
- 可能存在某些临界点(如LSTAT>20时价格急剧下降)
4.3 地理空间因素探索
虽然数据集不包含精确坐标,但我们可以用DIS(到就业中心距离)和RAD(高速公路可达性)作为空间代理:
plt.figure(figsize=(10, 6))
sns.scatterplot(x='DIS', y='PRICE', size='RM', hue='RAD',
data=df, palette='viridis', sizes=(20, 200), alpha=0.7)
plt.title('距离与房价关系(按房间数和可达性)')
plt.xlabel('到就业中心的加权距离')
plt.ylabel('价格(千美元)')
plt.legend(bbox_to_anchor=(1.05, 1), loc='upper left')
plt.show()
这种多变量散点图揭示了:
- 距离就业中心3-5英里的区域房价最高
- 高速公路可达性好的区域(RAD值高)房价普遍较高
- 远距离区域的房价与房间数关系更明显
5. 从可视化到建模决策
通过上述可视化分析,我们可以为后续建模提取关键指导:
-
特征选择:
- 重点关注RM、LSTAT、PTRATIO等高相关性特征
- 考虑CHAS作为分类变量加入模型
- 可能需要创建DIS和RAD的交互特征
-
数据变换:
- 对LSTAT尝试对数变换以处理非线性
- 考虑对PRICE进行变换处理右偏
- 标准化/归一化处理量纲差异
-
模型选择:
- 线性模型可能需要多项式特征
- 树模型可以自动捕捉非线性关系
- 考虑不同模型的解释性需求
-
异常值处理:
- 识别并检查高价异常值的合理性
- 决定保留或转换处理
# 示例:基于可视化洞察的特征工程
df['LOG_LSTAT'] = np.log1p(df['LSTAT'])
df['DIS_RAD'] = df['DIS'] / df['RAD']
# 可视化新特征与房价关系
plt.figure(figsize=(12, 4))
plt.subplot(121)
sns.scatterplot(x='LOG_LSTAT', y='PRICE', data=df, alpha=0.6)
plt.title('对数变换后的LSTAT与房价')
plt.subplot(122)
sns.scatterplot(x='DIS_RAD', y='PRICE', data=df, alpha=0.6)
plt.title('距离与可达性比率与房价')
plt.tight_layout()
plt.show()
这些基于可视化洞察的特征工程往往比盲目尝试更有效。在实际项目中,我会先用可视化理解数据故事,再让模型来量化这些关系,而不是相反。
更多推荐




所有评论(0)