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

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

一、项目背景
该项目是给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(探索性数据分析) 找到很多关于房价的影响因素。
相关推荐
Narutolxy1 小时前
大模型数据分析破局之路20250512
人工智能·chatgpt·数据分析
Ai尚研修-贾莲4 小时前
Python语言在地球科学交叉领域中的应用——从数据可视化到常见数据分析方法的使用【实例操作】
python·信息可视化·数据分析·地球科学
lilye665 小时前
精益数据分析(53/126):双边市场模式指标全解析与运营策略深度探讨
数据挖掘·数据分析
ʚɞ 短腿欧尼6 小时前
文本数据可视化
信息可视化·数据分析
安特尼9 小时前
招行数字金融挑战赛数据赛道赛题一
人工智能·python·机器学习·金融·数据分析
请你喝好果汁64111 小时前
TWASandGWAS中GBS filtering and GWAS(1)
信息可视化·数据挖掘·数据分析
Leo.yuan12 小时前
数据分析怎么做?高效的数据分析方法有哪些?
大数据·数据库·信息可视化·数据挖掘·数据分析
HsuHeinrich16 小时前
利用散点图探索宇航员特征与太空任务之间的关系
python·数据可视化
马志远的生信笔记17 小时前
质控脚本来喽
linux·数据分析
intcube17 小时前
集中运营、分散决策,寻找最佳财务规划的平衡点
大数据·信息可视化·数据分析·全面预算管理·财务管理·财务规划