查看全课大纲(第 5 / 35 节)

数据探索工具 Pandas_profiling

约 5 分钟

小象实战讲义 · 特征工程精讲与实践

在特征工程的完整流程中,数据探索是至关重要的一步。只有充分理解数据的分布、关系和潜在问题,我们才能为后续的特征构建、选择和建模打下坚实基础。本节我们将学习一个强大的自动化数据探索工具——pandas_profiling,它能够一键生成详尽的数据分析报告,帮助我们快速洞察数据全貌。

💡 核心导读

  • 工具定位:pandas_profiling 是一个基于 pandas DataFrame 的自动化探索式数据分析(EDA)工具库,能够一站式生成全面的数据报告。
  • 报告内容:报告涵盖数据概览、类型、缺失值、内存占用、分位数统计、描述性统计、分布直方图以及变量间相关性等关键信息。
  • 应用场景:适用于任何表格数据的初步探索阶段,尤其适合在特征工程前期快速了解数据集特性,为后续处理提供决策依据。
  • 输出形式:报告以交互式 HTML 文件形式输出,便于查看、分享和存档。

为什么需要自动化数据探索工具?

在数据科学和人工智能项目中,数据探索是一个不可或缺的环节。如果不了解业务背景和数据本身的特性(如分布、缺失、异常等),很难在后续使用通用方法取得理想的效果。

传统的数据探索方法因人而异,早期甚至有人使用 Excel 等工具进行手动分析。随着 Python 在数据分析领域的普及,我们拥有了更高效、更强大的工具。pandas_profiling 正是这样一个“一站式”工具库,它能自动计算并呈现数据分析中我们通常关心的各类统计信息,将结果以直观的报告形式展现出来。

Pandas_profiling 核心功能解析

pandas_profiling 基于 pandas 的 DataFrame(表格数据)进行构建,可以快速进行探索式数据分析。对于数据集中的每一列,它都会自动计算并提供以下统计信息:

  1. 概览(Overview):数据集的基本信息,包括变量类型、缺失值数量、内存占用等。
  2. 分位数统计(Quantile Statistics):对于数值型数据,提供最小值、最大值、中位数(50%分位数)、下四分位数(Q1)、上四分位数(Q3)等。这些是理解数据分布和范围的核心指标。
  3. 描述性统计(Descriptive Statistics):包括均值、众数(出现最多的取值)、标准差、绝对中位差(由分位数导出)、变异系数、峰度(Kurtosis)和偏度(Skewness)。后两者有助于我们判断数据分布与正态分布的差异。
  4. 分布直方图(Histogram):对数值型变量,自动绘制直方图,可视化其分布情况。
  5. 相关性分析(Correlations):计算并呈现变量之间的相关系数矩阵,帮助我们发现特征间的线性关系。

最终,所有这些分析结果会被整合成一个 HTML 格式的报告,方便我们查阅和分享。

实战:生成泰坦尼克号数据集报告

下面,我们使用一个微型化的泰坦尼克号数据集样例,演示如何使用 pandas_profiling 生成数据报告。请注意,为了确保代码的自包含和可复现,我们在代码块内直接构造了示例数据。

import pandas as pd

# 构造一个微型泰坦尼克号数据集样例
data = {
    'Pclass': [1, 1, 3, 2, 3, 1],  # 乘客等级
    'Age': [22.0, 38.0, 26.0, 35.0, 35.0, 54.0], # 年龄
    'Sex': ['male', 'female', 'female', 'male', 'male', 'female'], # 性别
    'Survived': [0, 1, 1, 0, 0, 1] # 是否幸存 (0=否, 1=是)
}
df_titanic = pd.DataFrame(data)

print("数据集预览:")
print(df_titanic)
print("\n数据集信息:")
print(df_titanic.info())
数据集预览:
   Pclass   Age     Sex  Survived
0       1  22.0    male         0
1       1  38.0  female         1
2       3  26.0  female         1
3       2  35.0    male         0
4       3  35.0    male         0
5       1  54.0  female         1

数据集信息:
<class 'pandas.DataFrame'>
RangeIndex: 6 entries, 0 to 5
Data columns (total 4 columns):
 #   Column    Non-Null Count  Dtype
---  ------    --------------  -----
 0   Pclass    6 non-null      int64
 1   Age       6 non-null      float64
 2   Sex       6 non-null      str
 3   Survived  6 non-null      int64
dtypes: float64(1), int64(2), str(1)
memory usage: 324.0 bytes
None

接下来,我们使用 pandas_profiling 生成报告。注意:pandas_profiling 不在本讲义的可运行代码白名单内,因此下面以伪代码形式展示生成报告的核心用法(text 围栏,不实际运行)。在实际环境中,你需要先安装该库(如 pip install pandas-profiling)才能运行。原课程中,该代码会生成一个名为 titanic_pf_report.html 的详细 HTML 报告。

# 以下为 pandas_profiling 生成报告的核心用法(需先安装 pandas-profiling)
from pandas_profiling import ProfileReport

profile = ProfileReport(df_titanic, title="Titanic Dataset Mini Report", explorative=True)
profile.to_file("titanic_pf_report_mini.html")

小贴士:该工具在社区后续版本中已更名为 ydata_profiling,新环境下可安装 ydata-profiling 并将导入改为 from ydata_profiling import ProfileReport,其余用法一致。

实战:生成链家租房数据集报告

我们再来看一个更贴近业务的数据集例子——链家租房数据。这个数据集可能包含更多现实世界的数据问题,如缺失值。我们同样先构造一个微型样例。

import pandas as pd

# 构造一个微型链家租房数据集样例,并模拟缺失值
data_lianjia = {
    '区域': ['朝阳', '海淀', '朝阳', '丰台', '海淀'],
    '户型': ['2室1厅', '1室0厅', '3室2厅', '2室1厅', '1室1厅'],
    '面积(平米)': [65.2, 45.5, 89.0, 60.8, 48.3],
    '租金(元/月)': [6800, 5200, 8500, 6200, 5000],
    '交通': ['近地铁', None, '近地铁', '附近无地铁', '近地铁'], # 模拟缺失值
    '供暖': ['集中供暖', '自采暖', '集中供暖', None, '集中供暖'] # 模拟缺失值
}
df_lianjia = pd.DataFrame(data_lianjia)

# 模拟原课程中的缺失值填充操作
df_lianjia['交通'] = df_lianjia['交通'].fillna("附近无地铁")
df_lianjia['供暖'] = df_lianjia['供暖'].fillna("自采暖")

print("链家租房数据预览(已处理缺失值):")
print(df_lianjia)
链家租房数据预览(已处理缺失值):
   区域    户型  面积(平米)  租金(元/月)     交通    供暖
0  朝阳  2室1厅    65.2     6800    近地铁  集中供暖
1  海淀  1室0厅    45.5     5200  附近无地铁   自采暖
2  朝阳  3室2厅    89.0     8500    近地铁  集中供暖
3  丰台  2室1厅    60.8     6200  附近无地铁   自采暖
4  海淀  1室1厅    48.3     5000    近地铁  集中供暖

对于这个数据集,pandas_profiling 的报告将能揭示出:

  • 面积(平米) 和 租金(元/月) 的数值分布、均值、中位数及它们之间可能存在的正相关性。
  • 区域、户型、交通、供暖 等类别型变量的取值分布(众数、唯一值数量)。
  • 报告只统计传入 DataFrame 当前状态的数据质量——若要留存”缺失情况”的完整记录,应在填充缺失值之前先对原始数据生成一份报告。

生成链家数据报告的核心用法与上面完全一致,只需把传入的 DataFrame 换成 df_lianjia、输出文件名换成 lianjia_report_mini.html 即可,此处不再重复展示。原课程中的教辅文件 lianjia_report.html 就是全量链家数据生成的完整报告,可在课程资料包中查看。

📝 动手练一练

  1. 概念辨析:pandas_profiling 生成的数据报告中,“分位数统计”部分包含中位数(Q2)。请问,对于一组数值数据,中位数的统计意义是什么?它与平均值(均值)在什么情况下会有显著差异?
👉 点击查看参考答案

中位数是将数据集按大小排序后位于中间位置的值。它的统计意义在于,它不受极端值(异常值)的影响,能够反映数据集的“中心位置”。当数据分布严重偏斜(Skewed)或存在极端值时,中位数与平均值会有显著差异。例如,在收入数据中,少数极高收入者会大幅拉高平均值,但中位数更能代表普通人的收入水平。

  1. 动手实践:假设你有一个包含“员工姓名”、“身高(cm)”、“部门”的微型数据集,其中“李四”的身高数据缺失。请仿照上面的例子,用 pandas 构造这个 DataFrame,并将身高缺失值填充为该部门的平均身高(需先计算)。最后打印出处理后的数据。
👉 点击查看参考答案
import pandas as pd
import numpy as np

# 构造数据
employee_data = {
    '姓名': ['张三', '李四', '王五', '赵六'],
    '身高(cm)': [175.0, np.nan, 180.0, 165.5], # 李四身高缺失
    '部门': ['技术部', '市场部', '技术部', '人事部']
}
df_emp = pd.DataFrame(employee_data)

# 计算各部门平均身高
dept_mean_height = df_emp.groupby('部门')['身高(cm)'].transform('mean')

# 用部门平均身高填充缺失值
df_emp['身高(cm)'] = df_emp['身高(cm)'].fillna(dept_mean_height)

print("处理后的员工数据:")
print(df_emp)

输出:

处理后的员工数据:
   姓名  身高(cm)   部门
0  张三   175.0  技术部
1  李四     NaN  市场部
2  王五   180.0  技术部
3  赵六   165.5  人事部

注意:groupby 的 transform('mean') 在计算时会忽略 NaN。“市场部”只有李四一人且其身高缺失,该组的均值本身为 NaN,因此填充未生效(结果仍为 NaN)。更健壮的做法是在部门均值之外再加一层兜底,例如用全公司平均身高填充剩余缺失:df_emp['身高(cm)'] = df_emp['身高(cm)'].fillna(df_emp['身高(cm)'].mean())。这个例子提醒我们:分组填充前先检查各组是否有可用观测。

本章小结

本节我们重点介绍了在特征工程前期用于快速理解数据的利器——pandas_profiling。它通过自动化生成包含概览、统计量、分布和相关性的综合报告,极大地提升了数据探索的效率和系统性。

📋 行动清单

  • 安装与尝试:在你的本地 Python 环境中安装 pandas-profiling 库(pip install pandas-profiling),并对自己手头的一个小数据集运行一遍,查看生成的 HTML 报告。
  • 报告解读:打开生成的报告,重点查看“警告”(Warnings)部分,识别数据中的缺失值、高基数类别特征、高度相关特征等常见问题。
  • 思考延伸:对比 pandas_profiling 的自动化报告与你平时手动使用 df.describe()、df.info() 和手动绘图进行探索的异同,思考在什么场景下更适合使用自动化工具。

—— 小象教研组