写在前面
上一篇博客,我们学习了如何灵活地索引和选取 DataFrame 中的数据,这为我们深入操作数据打下了基础。 然而,在我们拿到原始数据,准备开始大展身手进行分析之前,往往需要先进行一个至关重要的步骤:数据清洗与预处理 (Data Cleaning and Preprocessing)。
“脏数据”:数据分析路上的拦路虎
现实世界中的数据很少是完美无缺的,它们常常充满各种问题,也就是我们常说的 “脏数据”:
- 缺失值 (Missing Values): 数据表中存在空白单元格、
N/A
、NULL
等表示数据缺失的情况。例如,用户注册时未填写年龄、传感器数据采集失败等。 - 重复值 (Duplicate Values): 数据表中存在完全相同或部分字段相同的重复记录。例如,用户重复提交订单、数据导入过程中出错导致重复录入等。
- 异常值 (Outliers): 数据中存在明显偏离正常范围的极端值或错误值。例如,年龄填写为 200 岁、销售额出现负数等。
- 数据类型不一致 (Inconsistent Data Types): 同一列数据中包含不同的数据类型。例如,年龄列中既有数字,又有文本 “未知”。
- 格式不规范 (Inconsistent Formatting): 数据格式不统一。例如,日期格式有 “2023-10-27”、“10/27/2023”、“2023年10月27日” 等多种形式;文本数据大小写混乱、包含多余空格等。
这些 “脏数据” 如果不进行处理,将会严重影响数据分析的准确性和可靠性,甚至导致错误的结论。 “Garbage in, garbage out” (垃圾进,垃圾出) 这句名言深刻地说明了数据质量的重要性。
Excel 数据清洗的繁琐与局限:
在 Excel 中,我们通常需要手动或使用一些内置功能来处理这些问题:
- 处理缺失值: 手动查找替换、使用筛选功能定位空值、编写复杂的 IF 函数填充等,操作繁琐且容易出错。
- 处理重复值: 使用 Excel 的 “删除重复项” 功能,但对于复杂的重复判断(例如基于部分列判断)不够灵活。
- 处理异常值: 通常需要手动筛选、排序来查找,或编写复杂的条件格式规则,难以自动化处理。
- 处理不一致的数据类型和格式: 需要手动修改单元格格式、使用文本函数 (如
TRIM
,UPPER
,LOWER
) 清理文本,工作量大且易出错。
Pandas 数据清洗:高效、灵活、自动化的解决方案
Pandas 提供了 强大、高效、灵活 的数据清洗和预处理功能,让处理 “脏数据” 变得更加轻松和自动化:
- 高效识别和处理缺失值: Pandas 使用
NaN
(Not a Number) 表示缺失值,并提供了isnull()
,notnull()
,dropna()
,fillna()
等函数,可以方便地检测、删除或填充缺失值。 - 轻松处理重复值: Pandas 提供了
duplicated()
和drop_duplicates()
函数,可以快速检测和删除重复行。 - 灵活处理异常值: 结合 Pandas 的数据选取、条件筛选和统计功能,可以灵活地检测和处理异常值 (本篇仅作初步介绍)。
- 强大的数据类型转换和格式化功能: Pandas 提供了
astype()
,pd.to_numeric()
,pd.to_datetime()
等函数,可以方便地进行数据类型转换。 结合.str
和.dt
访问器,可以高效地处理文本和日期时间数据 (将在下一篇详细介绍)。
本篇博客将作为数据清洗与预处理系列的上篇,重点讲解如何使用 Pandas 处理数据分析中最常见的三类 “脏数据”:缺失值、重复值和异常值 (初步介绍)。
💧 一、处理缺失值 (Missing Values):填补数据的空白
缺失值 (Missing Values) 是数据分析中最常见的问题之一。 Pandas 使用 NaN
(Not a Number) 来表示缺失的数值型数据和时间序列数据。 对于对象类型 (例如字符串),Pandas 也可能使用 None
或 NaN
来表示缺失值。 处理缺失值通常有两种主要方法:删除 (Dropping) 或 填充 (Filling)。
1. 检测缺失值
在处理缺失值之前,首先需要 检测 数据中是否存在缺失值,以及缺失值的分布情况。 Pandas 提供了几个常用的方法来检测缺失值:
-
isnull()
或isna()
: 这两个方法功能相同,返回一个与原 DataFrame 或 Series 形状相同 的 布尔对象,其中缺失值位置为True
,非缺失值位置为False
。import pandas as pd import numpy as np data = { 'A': [1, 2, np.nan, 4], 'B': [5, np.nan, np.nan, 8], 'C': [9, 10, 11, 12]} df = pd.DataFrame(data) print("原始 DataFrame:\n", df) print("\n检测缺失值 (isnull()):\n", df.isnull()) print("\n检测缺失值 (isna()):\n", df.isna())
输出:
原始 DataFrame: A B C 0 1.0 5.0 9 1 2.0 NaN 10 2 NaN NaN 11 3 4.0 8.0 12 检测缺失值 (isnull()): A B C 0 False False False 1 False True False 2 True True False 3 False False False 检测缺失值 (isna()): A B C 0 False False False 1 False True False 2 True True False 3 False False False
-
notnull()
或notna()
: 这两个方法功能相同,与isnull()
/isna()
相反,返回一个布尔对象,其中非缺失值位置为True
,缺失值位置为False
。print("\n检测非缺失值 (notnull()):\n", df.notnull()) print("\n检测非缺失值 (notna()):\n", df.notna())
-
结合
sum()
方法统计缺失值数量: 将isnull()
或isna()
返回的布尔对象与sum()
方法结合使用,可以快速统计 每列 或 每行 的缺失值数量 (因为True
在求和时被视为 1,False
被视为 0)。print("\n每列缺失值数量:\n", df.isnull().sum()) # 默认按列统计 (axis=0) print