第27课:探索性数据分析(EDA)方法与实践
学习目标
通过本课的学习,你将能够:
- 理解探索性数据分析(EDA)在机器学习工作流中的重要性和核心目标。
- 掌握对数据集进行初步“体检”的通用方法,包括检查数据形状、类型、缺失值等。
- 学会使用描述性统计和基础可视化技术(如直方图、散点图)来发现数据的模式、异常和关系。
- 培养从数据中提出假设并进行验证的初步思维,为后续的特征工程和建模打下坚实基础。
核心概念
想象一下,你得到了一个装满未知数据的“黑盒子”(数据集)。在试图用它建造复杂的模型(机器学习)之前,你首先要做的,就是打开盒子,仔细观察和了解里面到底有什么。探索性数据分析就是这个“观察和了解”的过程。
EDA 的核心目标不是建立模型,而是通过汇总统计和可视化等手段,深入理解数据的内在结构、特征分布、变量间关系,并发现潜在的问题(如异常值、错误数据)。它是一个迭代的过程,始于问题,终于洞见。
我们可以把 EDA 流程简化为一个清单:
- 初次见面:数据有多大?(行列数)
- 明辨身份:每列是什么数据类型?(数值型、类别型、文本型)
- 寻找空缺:有没有缺失值?缺失严重吗?
- 概括描述:用统计数字描述数据的“长相”(均值、中位数、分位数等)。
- 直观描绘:用图表看看数据的真实分布和关系。
代码示例
我们将使用经典的 泰坦尼克号生存数据集 来进行一个完整的 EDA 演示。请确保你的环境中安装了必要的库 (pandas, numpy, matplotlib, seaborn)。
# 导入所需库
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
# 设置图形风格和中文显示
sns.set_style("whitegrid")
plt.rcParams['font.sans-serif'] = ['SimHei'] # 用于正常显示中文标签
plt.rcParams['axes.unicode_minus'] = False # 用于正常显示负号
%matplotlib inline
# 加载数据集(你可以从Seaborn内置数据集中加载)
df = sns.load_dataset('titanic')
# ---- 第一步:初步观察 ----
print("=" * 50)
print("第1步:数据的形状")
print(f"数据集有 {df.shape[0]} 行,{df.shape[1]} 列")
print("\n第2步:查看前5行数据")
print(df.head())
# ---- 第二步:数据类型与缺失值检查 ----
print("\n第3步:数据类型与非空值数量")
print(df.info())
print("\n第4步:缺失值统计")
missing_values = df.isnull().sum()
print(missing_values[missing_values > 0])
# ---- 第三步:描述性统计 ----
print("\n第5步:数值型列的描述性统计")
print(df.describe())
print("\n第6步:类别型列的描述性统计(包括计数和唯一值)")
print(df.describe(include=['category', 'object']))
# ---- 第四步:可视化探索 ----
# 图1:生存情况分布(类别变量)
plt.figure(figsize=(6, 4))
sns.countplot(x='survived', data=df)
plt.title('生存情况分布 (0:遇难, 1:生还)')
plt.show()
# 图2:年龄分布直方图(数值变量)
plt.figure(figsize=(8, 5))
sns.histplot(df['age'].dropna(), kde=True, bins=30)
plt.title('乘客年龄分布')
plt.xlabel('年龄')
plt.show()
# 图3:不同舱位等级(Pclass)的生存率对比
plt.figure(figsize=(6, 4))
sns.barplot(x='pclass', y='survived', data=df)
plt.title('不同舱位等级乘客的生存率')
plt.ylabel('生存率')
plt.show()
# 图4:票价(Fare)与年龄(Age)的关系散点图,并按生存情况着色
plt.figure(figsize=(10, 6))
sns.scatterplot(x='age', y='fare', hue='survived', data=df, alpha=0.6)
plt.title('年龄、票价与生存情况的关系')
plt.xlabel('年龄')
plt.ylabel('票价')
plt.show()
实践练习
请基于下面的数据(或使用你自己找到的简单数据集,如iris或tips),完成 EDA 流程。
假设数据集:一家网店的销售记录,包含 order_id (订单ID), product_category (产品类别), price (价格), quantity (数量), order_date (下单日期), customer_city (客户所在城市)。
-
基础检查:假设你已经用
pd.read_csv()将数据加载到了变量sales_df中。请写出代码,打印出它的形状、前3行,以及各列的数据类型。- 预期输出示例:
数据形状: (1000, 6) 前3行: ... 数据类型: order_id int64 product_category object ...
- 预期输出示例:
-
分析与可视化: a) 计算并打印数据集中“产品类别”的数量。 b) 绘制一个柱状图,展示不同“产品类别”的平均订单金额(
price * quantity)。 c) 绘制一个饼图,展示来自不同“客户城市”的订单占比。 -
提出假设:观察你生成的图表后,写一句话描述你从数据中发现的一个潜在现象或规律(例如:“服装类产品的平均订单金额最高”,或“超过60%的订单来自A城市”)。
常见错误
- 跳过EDA直接建模:这是最严重的错误。不了解数据就建模,就像不看图纸就盖房子,结果往往不可靠。
- 只看平均数,忽略分布:只关注
describe()输出的均值,而忽略了数据的分布(如直方图、箱线图)。两个均值相同的变量,其分布可能截然不同(如一个很集中,一个很分散)。 - 错误地处理缺失值:在EDA阶段,应先理解缺失值产生的原因(随机缺失?特定人群缺失?),再决定是删除、填充还是将其作为一种特征。盲目地用均值填充所有缺失值可能掩盖重要信息。
- 混淆相关性与因果性:散点图显示两个变量相关,不代表其中一个导致了另一个。EDA能发现关联,但因果推断需要更严谨的方法。
- 图表可读性差:忘记添加标题、坐标轴标签、图例,或者使用了不合适的图表类型(如用折线图表示类别数据),都会让分析效果大打折扣。
小结
本课我们系统地学习了探索性数据分析的基本方法和流程:
- EDA是基础:它是任何数据科学项目的必经之路,目的是理解数据、发现洞见、识别问题。
- 流程化操作:从检查数据“长相”(形状、类型、缺失)开始,到用统计数字进行概括,最后用可视化让数据“说话”。
- 核心工具:Pandas 的
head(),info(),describe(),isnull().sum()是你的体检工具;Matplotlib 和 Seaborn 是你的“透视镜”。 - 思维培养:EDA 不仅是技术操作,更培养一种“数据直觉”和提出问题、验证假设的思维习惯。
记住,EDA 是一个迭代的过程。你常常会根据可视化的结果,回过头去重新检查数据质量或探索新的角度。完成扎实的 EDA 后,你才能自信地进入下一个环节——特征工程与模型构建。