数据分析实战一:波士顿房价

波士顿房价数据分析项目实战

一、项目背景
该项目是给Ashely同学写的基础入门教程,所以会尽量避免涉及机器学习算法,尽可能的简单易懂,方便其快速上手。

波士顿房价数据(Boston Housing Dataset)是一个经典的房价数据集,包含了波士顿不同地区的一些特征信息(例如房屋面积、房产税率、空气污染指数、周边犯罪率等),以及相应的房价中位数。我们将以此数据集作为示例,进行一次基础的数据分析项目,体验完整的数据分析流程。

本次项目的主要目标:

  1. 理解数据结构:包括数据集中有哪些列,每列代表的含义,以及数据的基本分布情况等。
  2. 数据清洗与预处理:检查缺失值、异常值等,保证数据质量。
  3. 探索性数据分析(EDA):进行可视化和统计分析,初步了解变量之间的关系、分布特点等。 本次项目会尽量避免机器学习的内容,更多聚焦于数据本身的清洗、统计和可视化分析上。

开发环境的安装

  • 执行下面命令,用于安装项目依赖的库函数
  • !pip install -r requirements.txt
  • 前面有一个感叹号,代表这行代码是一个命令行命令,而不是 Python 代码
  • 这行代码的作用是安装项目依赖的库函数,具体来说是安装 requirements.txt 文件中列出的所有库函数
  • 安装完成后,就可以在项目中使用这些库函数了

Python库函数入门指南

Ashely同学看黑板(敲一敲):

在开始数据分析的旅程前,让我先为你介绍一下Python中的"库函数"。想象一下,如果把Python比作一个巨大的工具箱,那么这些库函数就像是里面不同功能的工具。我们不需要每次都自己制造工具,只要通过import语句,就能直接使用这些现成的强大工具。

为什么要使用库函数?

想象你要在Excel里处理数据时,会用到"求和"、"平均值"等函数,这些都是Excel内置的工具。在Python中,库函数就起着类似的作用,但功能更加强大和灵活。

我们项目中用到的主要库函数
1. pandas (pd)

pandas就像是一个超级强大的Excel,专门用来处理表格数据。

python 复制代码
import pandas as pd

# 例子:创建一个简单的成绩表
成绩表 = pd.DataFrame({
    '姓名': ['小明', '小红', '小华'],
    '语文': [85, 92, 78],
    '数学': [95, 88, 82]
})
print(成绩表)
2. numpy (np)

numpy就像是一个超级计算器,特别擅长处理数学计算。

python 复制代码
import numpy as np

# 例子:计算班级平均分
班级分数 = [85, 92, 78, 95, 88]
平均分 = np.mean(班级分数)
print(f"班级平均分是:{平均分}")
3. matplotlib.pyplot (plt)

matplotlib就像是一个画图工具,可以把数据变成图表。

python 复制代码
import matplotlib.pyplot as plt

# 例子:画出销售趋势图
月份 = ['1月', '2月', '3月', '4月']
销量 = [120, 150, 180, 210]

plt.plot(月份, 销量)
plt.title('月度销售趋势')
plt.xlabel('月份')
plt.ylabel('销量')
plt.show()
类比
  1. pandas就像一个图书管理员

    • 可以帮你整理、查找、排序大量的数据
    • 就像图书管理员知道每本书在哪个架子上一样
  2. numpy就像一个数学天才

    • 可以快速进行复杂的数学运算
    • 比如计算100个数字的平均值,只需一行代码
  3. matplotlib就像一个画家

    • 能把枯燥的数字变成生动的图表
    • 帮助我们更直观地理解数据
小贴士
  • 我们用import pandas as pd这样的写法,是给pandas起了个简短的别名"pd",这样后面使用时就不用每次都写完整的名字了,就像给好朋友起昵称一样。
  • 在代码中看到plt.np.pd.开头的命令,就表示我们在使用这些库提供的功能。
python 复制代码
# pandas 是一个处理表格数据(DataFrame)的常用库
import pandas as pd

# numpy 是常用的数值运算库
import numpy as np

import seaborn as sns 
import matplotlib.pyplot as plt
# 设置全局字体为支持中文的字体
# 你是windows系统,所以使用SimHei字体
plt.rcParams['font.sans-serif'] = ['SimHei']  # Windows系统使用SimHei
# plt.rcParams['font.sans-serif'] = ['Arial Unicode MS']  # MacOS系统
# plt.rcParams['font.sans-serif'] = ['WenQuanYi Micro Hei']  # Linux系统

# 解决负号显示问题
plt.rcParams['axes.unicode_minus'] = False

读取数据

python 复制代码
# 通常我们会有一个 CSV文件 从中获取波士顿房价数据
df = pd.read_csv('house_data.csv')

# 现在 df 就是一个 DataFrame 类型的数据表格
df.head()  # 查看前 5 行数据

输出结果如下:

初步了解数据的维度、列信息和数据类型

python 复制代码
# 查看数据的形状(行数 x 列数)
print("数据集的行数和列数:", df.shape)

# 查看所有列及其对应的数据类型
print("\n列名和数据类型:")
print(df.dtypes)

# 查看各个列的简要统计描述
print("\n各列的统计摘要:")
df.describe()

输出结果如下:

df.describe()就不在此贴出来啦,自己上notebook上看

特征变量含义

现在我们知道了数据的各行各列都是些什么东西了,但是具体是表示什么含义呢?接下来我解释一下各个特征变量的含义:

基础特征
  • CRIM:该地区的人均犯罪率

    • 反映了社区的安全程度
    • 通常与房价呈负相关关系
  • ZN:占地面积超过25000平方英尺的住宅用地比例

    • 反映了区域的开发密度
    • 较高的比例通常意味着更多的低密度住宅区
  • INDUS:每个城镇非零售商业用地的比例

    • 反映了工业化程度
    • 可能影响居住环境质量
环境特征
  • CHAS:是否临近查尔斯河

    • 1 = 临近
    • 0 = 不临近
    • 临近水域通常被视为较好的居住环境
  • NOX:一氧化氮浓度(每千万份中的部分)

    • 重要的空气质量指标
    • 反映了环境污染程度
房屋特征
  • RM:每栋住宅的平均房间数

    • 直接反映房屋大小
    • 是最重要的价格影响因素之一
  • AGE:1940年之前建成的自住单位比例

    • 反映建筑年代
    • 可能影响房屋维护成本
位置特征
  • DIS:到波士顿五个就业中心的加权距离

    • 反映通勤便利性
    • 对房价有显著影响
  • RAD:到径向公路的可达性指数

    • 反映交通便利程度
    • 影响生活便利性
经济因素
  • TAX:每一万美元的房产税率

    • 直接影响房屋持有成本
    • 较高税率可能降低房价
  • PTRATIO:城镇师生比例

    • 反映教育资源质量
    • 是购房者重要考虑因素
人口统计学特征
  • B:1000(Bk - 0.63)^2

    • 其中Bk是城镇中黑人的比例
    • 反映种族构成情况
  • LSTAT:低收入人群的比例

    • 反映邻里社会经济状况
    • 通常与房价呈负相关
目标变量
  • MEDV :自住房的中位数价值
    • 单位:千美元
    • 这是我们要分析的目标变量

数据清洗与预处理

做完上面的事情,你仔细思考一下这个问题---我们是不是遗漏了什么?很明显,我们拿到 数据,不管三七二十一直接开始用了,这是非常不好的习惯!我们应该先对数据进行一些处理,让它符合我们进行分析的标准,这才是正确的顺序!

为什么需要数据清洗?

想象你在整理一个Excel表格,可能会遇到:

  • 有些单元格是空的(缺失值)
  • 有些行的内容重复了(重复值)
  • 有些数据明显不对(异常值)

这些问题如果不处理,就会影响我们后面的分析结果。

我们要检查什么?
  1. 缺失值检查

    • 查看是否有空值
    • 如果有,需要决定是删除还是填补
  2. 重复值检查

    • 查看是否有完全相同的数据行
    • 重复的数据可能会影响分析结果
  3. 异常值检查(这个我们后面会用可视化的方式来看)

    • 比如房价不可能是负数
    • 房间数不可能是小数
处理方法
  • 对于缺失值

    • 可以直接删除(如果缺失很少)
    • 可以用平均值填充
    • 可以用相似数据的值填充
  • 对于重复值

    • 通常直接删除重复行
    • 但要先确认是否是真的重复

让我们开始动手清洗数据吧!

python 复制代码
# 数据清洗与预处理:检查缺失值、重复值


# 1)检查缺失值
print("缺失值情况:")
print(df.isnull().sum())

# 一般如果有缺失值,可以考虑删除或填补。这里我们先查看是否存在缺失值。
# 如果不存在缺失值,就不需要额外处理。

# 2)检查重复值
# 对于绝大多数数值型数据来说,不常见完全重复的行,但还是可以检查一下:
duplicates = df.duplicated()
print("\n是否存在重复行:", duplicates.any())  # any() 若有一个True就返回True
if duplicates.any():
    # 如果有重复行,可以考虑删除
    df = df.drop_duplicates()
    print("删除重复行后,数据形状:", df.shape)
else:
    print("太好啦!没有发现重复行。")

运行后的结果:

统计分析

通过上面的操作,我们已经对数据有了基本的了解,并且也对其进行了清洗和预处理。现在让我们通过图表的形式,进行一些统计学上的分析! 这里我们主要从以下几个方面来了解数据:

  • 各列的大致分布,如均值、中位数、标准差
  • 房价(MEDV)的分布和一些有意义的特征关系
  • 有些特征之间可能存在强相关
python 复制代码
# 1) 直接查看房价(MEDV)的分布情况
plt.figure(figsize=(10,5))
plt.hist(df['MEDV'], bins=30, color='skyblue', edgecolor='black')
plt.title("房价(MEDV)分布直方图")
plt.xlabel("房价中位数")
plt.ylabel("频数(出现次数)")
plt.show()

# 2) 查看其它一些重要特征的分布,如 'CRIM'(犯罪率)、'RM'(平均房间数)
# 为了演示,这里举例只画一个特征的分布,其他特征可以相同方式自行分析
plt.figure(figsize=(10,5))
plt.hist(df['CRIM'], bins=30, color='salmon', edgecolor='black')
plt.title("犯罪率(CRIM)分布直方图")
plt.xlabel("犯罪率")
plt.ylabel("频数")
plt.show()

结果显示如下:

波士顿房价分布特征分析

从直方图中我们可以观察到以下特点:

  1. 分布形状

    • 整体呈现不对称的分布
    • 有明显的右偏(正偏)特征
    • 在20-25千美元区间出现最高峰
  2. 数据集中趋势

    • 大多数房价集中在15-35千美元之间
    • 最集中的区域在20-25千美元附近
    • 中位数约在20千美元左右
  3. 异常值特征

    • 在50千美元附近有一个小峰值
    • 这可能表示存在一些高端房产
    • 这些高价房产可能位于特殊位置或具有特殊特征
  4. 价格区间分布

    • 低价区(<15千美元):较少
    • 中价区(15-35千美元):最常见
    • 高价区(>35千美元):逐渐减少,但在50千美元处有小幅上升
  5. 市场启示

    • 波士顿房市以中等价位房产为主
    • 存在一定数量的高端房产市场
    • 低价房产相对较少

犯罪率(CRIM)分布特征分析

从直方图中我们可以观察到以下特点:

  1. 高度偏斜分布

    • 呈现极度右偏(正偏)的分布形态
    • 绝大多数区域的犯罪率都集中在较低水平
    • 在接近0的位置有一个非常高的峰值
  2. 数据集中特征

    • 约350个地区的犯罪率都非常低(接近0)
    • 随着犯罪率增加,地区数量急剧减少
    • 大部分地区的犯罪率都在20以下
  3. 长尾特征

    • 图形右侧有一个很长的尾部
    • 少数地区的犯罪率明显高于平均水平
    • 最高犯罪率接近80,但这种情况非常罕见
  4. 社会意义

    • 波士顿大多数地区的治安状况良好
    • 存在少数犯罪率较高的"问题区域"
    • 这种分布对房价可能有显著影响
  5. 数据分析建议

    • 由于分布极度偏斜,在后续分析中可能需要考虑数据转换
    • 对异常高值的区域可能需要特别关注
    • 在建模时需要考虑这种非正态分布的特征

进一步的可视化分析:关系分析

python 复制代码
# 数据分析中,一个常用的手段就是查看不同特征之间是否存在关联性。
# 我们可以用散点图(Scatter Plot)来查看两个连续数值型变量之间的关系。
# 比如,房间数(RM) 与 房价(MEDV) 之间是否有关系。

plt.figure(figsize=(8,6))
plt.scatter(df['RM'], df['MEDV'], alpha=0.6, color='teal')
plt.title("平均房间数(RM) vs. 房价(MEDV)")
plt.xlabel("平均房间数(RM)")
plt.ylabel("房价中位数(MEDV)")
plt.show()

平均房间数与房价关系分析

从散点图中我们可以观察到以下重要特征:

  1. 明显的正相关关系

    • 随着房间数的增加,房价总体呈上升趋势
    • 这种关系呈现出较为明显的线性特征
    • 说明房间数是影响房价的重要因素之一
  2. 数据分布特征

    • 大多数房屋的平均房间数在5-7间之间
    • 房价主要集中在10-35千美元区间
    • 数据点的密度在中间区域最高
  3. 特殊点分布

    • 在房价50千美元附近有一条"天花板"
    • 存在一些离群点,特别是在高房间数区域
    • 少数房屋即使房间数较多,房价也可能较低
  4. 趋势变化

    • 在房间数较少时(<6),房价变化相对平缓
    • 在房间数较多时(>7),房价上升更快
    • 这表明房价与房间数的关系可能不是完全线性的
  5. 实际意义

    • 房间数可以作为预测房价的重要指标
    • 但仅凭房间数无法完全解释房价变化
    • 可能还需要考虑其他因素(如位置、年代等)

相关系数矩阵(Correlation Matrix)

python 复制代码
# 相关系数矩阵可以让我们快速查看各个变量之间的相关程度。
# 相关系数在 -1 和 1 之间,越接近 1 表示正相关,越接近 -1 表示负相关,接近 0 表示弱相关。

corr_matrix = df.corr()
plt.figure(figsize=(12, 10))
sns.heatmap(corr_matrix, annot=False, cmap='YlGnBu')
plt.title("相关系数矩阵(Heatmap)")
plt.show()

# 我们可以重点关注 MEDV 那一列(或那一行),看看哪个特征和房价相关性最强。
corr_with_MEDV = corr_matrix['MEDV'].sort_values(ascending=False)
print("与房价(MEDV)相关性由高到低排序:\n", corr_with_MEDV)

相关系数矩阵分析

这个热力图展示了各个特征之间的相关性,颜色越深表示相关性越强,颜色越浅表示相关性越弱。

  1. 与房价(MEDV)的相关性

    • 最强正相关:RM(房间数),呈现深蓝色
    • 最强负相关:LSTAT(低收入人群比例),呈现浅色
    • 其他显著相关:
      • PTRATIO(师生比):负相关
      • NOX(空气污染):负相关
      • CRIM(犯罪率):负相关
  2. 特征间的重要相关性

    • TAX(房产税)和RAD(公路可达性)强相关
    • NOX(空气污染)和INDUS(工业用地比例)强相关
    • AGE(房龄)和DIS(到就业中心距离)有一定相关性
  3. 关键发现

    • 房价与房屋物理特征(如房间数)呈正相关
    • 房价与环境问题(污染、犯罪)呈负相关
    • 房价与社会经济因素(低收入人群比例)呈负相关
  4. 数据建议

    • 在建模时需要注意多重共线性问题
    • 可以考虑选择相关性强且互不相关的特征
    • 特别关注与房价强相关的几个关键变量
  5. 实际意义

    • 房价受多个因素综合影响
    • 物理特征、环境因素和社会因素都很重要
    • 这些相关性可以帮助购房者更好地评估房产

参数解析:

波士顿房价相关性分析

各特征与房价(MEDV)的相关性排序(从高到低):

特征变量 相关系数 相关性说明
MEDV 1.000000 完全相关(房价本身)
RM 0.695360 强正相关(房间数量)
ZN 0.360445 弱正相关(住宅用地比例)
B 0.333461 弱正相关(黑人比例)
DIS 0.249929 弱正相关(距离就业中心的加权距离)
CHAS 0.175260 极弱正相关(是否临近查尔斯河)
AGE -0.376955 弱负相关(建筑年龄)
RAD -0.381626 弱负相关(公路可达性)
CRIM -0.388305 弱负相关(犯罪率)
NOX -0.427321 中等负相关(一氧化氮浓度)
TAX -0.468536 中等负相关(财产税率)
INDUS -0.483725 中等负相关(非零售业务比例)
PTRATIO -0.507787 中等负相关(师生比例)
LSTAT -0.737663 强负相关(低收入人群比例)

相关性强度参考标准:

  • 相关系数 > 0.7:强相关
  • 0.4 < 相关系数 ≤ 0.7:中等相关
  • 0.2 < 相关系数 ≤ 0.4:弱相关
  • 相关系数 ≤ 0.2:极弱相关

分箱分析或箱线图(Box Plot)- 检查异常值、分布特征

python 复制代码
# 以房价(MEDV)为例,画一个箱线图(Box Plot)。
# 箱线图能帮助我们判断数据的四分位数、是否有离群点等。
plt.figure(figsize=(8,6))
sns.boxplot(y=df['MEDV'], color='lightblue')
plt.title("房价(MEDV)的箱线图")
plt.ylabel("房价中位数(MEDV)")
plt.show()

# 我们也可以同时对多个特征做箱线图,但通常情况下,先针对关键特征逐一查看。

房价箱线图分析

箱线图展示了房价数据的分布特征和异常值情况:

  1. 核心分布区间

    • 箱体(第一四分位数到第三四分位数)大约在17-25千美元之间
    • 中位数(箱体中的横线)约在21千美元
    • 这表示50%的房价都集中在这个区间
  2. 离群值特征

    • 上方有多个离群点,主要集中在40-50千美元区间
    • 这些可能是高档住宅区或特殊位置的房产
    • 离群值的存在表明房价分布有明显的右偏特征
  3. 分布对称性

    • 箱体中位线不在箱体中央
    • 上下须线长度不等
    • 这表明房价分布不是完全对称的
  4. 数据范围

    • 正常范围(不包括离群值):约5-35千美元
    • 总体范围(包括离群值):约5-50千美元
    • 价格跨度较大,反映了房市的多样性
  5. 实际意义

    • 大多数房产价格较为集中
    • 存在明显的高端房产市场
    • 极低价房产相对较少

分组对比分析(假设有分类变量时)

python 复制代码
# 在波士顿房价数据集中,大多数特征都是连续数值,没有明显的分类变量。
# 如果有,比如你希望查看在不同 "CHAS"(查尔斯河) 取值(0 或 1)下,房价分布如何,
# 可以使用分组对比分析。
# CHAS: 是否靠近查尔斯河(1表示是,0表示否)

plt.figure(figsize=(10,6))
sns.boxplot(x=df['CHAS'], y=df['MEDV'], palette='Set2')
plt.title("是否靠近查尔斯河与房价的关系")
plt.xlabel("CHAS (0 = 不靠近, 1 = 靠近)")
plt.ylabel("房价中位数(MEDV)")
plt.show()

# 通过这个箱线图,可以对比靠近和不靠近查尔斯河的两个组在房价上的差别。

查尔斯河临近性与房价关系分析

这个箱线图比较了临近查尔斯河(CHAS=1)和不临近查尔斯河(CHAS=0)的房价分布情况:

  1. 中位数比较

    • 临近查尔斯河的房价中位数约为23千美元
    • 不临近查尔斯河的房价中位数约为21千美元
    • 临近河边的房价普遍更高
  2. 价格分布范围

    • 临近河边(CHAS=1):
      • 箱体范围更大,约20-33千美元
      • 价格波动更大
    • 不临近河边(CHAS=0):
      • 箱体范围较小,约17-25千美元
      • 价格相对更稳定
  3. 离群值特征

    • 两类位置都存在高价离群值
    • 不临近河边的房产有更多的离群值点
    • 最高价格都接近50千美元
  4. 分布形态

    • 临近河边的房价分布更分散
    • 不临近河边的房价分布更集中
    • 两种情况都呈现右偏分布
  5. 市场启示

    • 临近查尔斯河确实会带来房价溢价
    • 但位置因素并不是决定房价的唯一因素
    • 其他因素(如房屋条件)可能影响更大

总结

至此,我们已经完成了第一阶段的学习。在这个教程中:

  1. 我们初步了解了波士顿房价数据的结构、各列含义以及分布情况。
  2. 做了简单的数据清洗,发现数据中并没有缺失值,也没有重复值。
  3. 通过可视化和相关性分析,了解到以下有趣的现象:
    • 房间数(RM)和房价(MEDV)之间存在明显的正相关。
    • LSTAT(低收入人群比例)和房价(MEDV)有显著的负相关。
    • 其他一些特征,如犯罪率(CRIM),对房价也有一定影响,但强度不及RM和LSTAT。
  4. 在没有深入机器学习的情况下,我们也可以通过 EDA(探索性数据分析) 找到很多关于房价的影响因素。
相关推荐
酱学编程5 小时前
数据分析工作流
数据挖掘·数据分析
Anna_Tong12 小时前
引领实时数据分析新时代:阿里云实时数仓 Hologres
大数据·阿里云·数据分析·实时数仓
生信碱移14 小时前
万字长文:机器学习的数学基础(易读)
大数据·人工智能·深度学习·线性代数·算法·数学建模·数据分析
枝上棉蛮15 小时前
借助免费GIS工具箱轻松实现las点云格式到3dtiles格式的转换
gis·数据可视化·3dtiles·文件格式转换·gis工具箱·las点云数据
全球认证考试中心15 小时前
Powerbi官方认证!2025年入行数据分析
数据挖掘·数据分析·powerbi
smilejingwei18 小时前
Excel 做数据分析的好与不好
数据分析·excel·spl·esprocspl
Flerken10120 小时前
EXCEL: (二) 常用图表
数据分析·excel
Allen_LVyingbo21 小时前
英伟达 RTX 5090 显卡赋能医疗大模型:变革、挑战与展望
数据分析·健康医疗·集成学习
B站计算机毕业设计超人1 天前
计算机毕业设计Python+Spark中药推荐系统 中药识别系统 中药数据分析 中药大数据 中药可视化 中药爬虫 中药大数据 大数据毕业设计 大
大数据·python·深度学习·机器学习·课程设计·数据可视化·推荐算法