45·模块十:数据处理与分析进阶

pandas 数据清洗与操作

pandasdata-manipulationcleaning

Python 编程:从零基础到精通

第45课 - pandas 数据清洗与操作

模块十:数据处理与分析 | 难度:intermediate | 标签:pandas, data-manipulation, cleaning 上一课: 数据分析:pandas 入门与 DataFrame 下一课: 数据可视化:Matplotlib 基础


1. 学习目标

完成本课学习后,你将能够:

  • 掌握使用 pandas 处理缺失值(NaN)的常用方法。
  • 学会识别和处理重复数据。
  • 熟练进行数据类型的转换和列的重命名。
  • 运用字符串方法清洗和格式化文本数据。
  • 能够根据条件筛选、替换和修改数据。

2. 核心概念

2.1 处理缺失值(Missing Values)

在真实世界的数据集中,经常会有数据缺失的情况,pandas 用 NaN (Not a Number) 来表示。处理缺失值是数据清洗的第一步,常见策略有删除、填充或插值。

通俗比喻:想象一盒拼图,其中几块缺失了。你可以选择:1)把缺失块周围的拼图都扔掉(删除行/列);2)找一块相似颜色的硬纸板补上(填充);3)根据周围的图案猜测缺失块的样子(插值)。

2.2 处理重复数据

数据中可能因为录入错误、系统合并等原因出现完全相同的行。duplicated() 方法可以找出重复行,而 drop_duplicates() 可以删除它们。

2.3 数据类型转换与重命名

数据类型(如整数、浮点数、字符串、日期时间)必须正确,才能进行正确的计算和分析。astype() 用于转换类型,rename() 用于更改列名或索引名,使其更清晰、规范。

2.4 字符串数据操作

当数据包含文本时,需要标准化处理。pandas 提供了 .str 访问器,可以像操作 Python 字符串一样,批量处理 DataFrame 中的文本列,如提取、替换、分割、大小写转换等。

2.5 条件数据替换与筛选

根据特定条件来修改或筛选数据,是数据清洗和准备的核心。例如,将异常值标记为缺失、将分类变量进行编码等。

3. 代码示例

以下是一个完整的、可运行的示例,演示了常见的数据清洗操作。

import pandas as pd
import numpy as np

# 创建一个包含常见"脏"数据的示例DataFrame
data = {
    '姓名': ['张三', '李四', '王五', '赵六', '孙七', '张三'],  # 注意:'张三'重复了
    '年龄': [28, 35, np.nan, 42, 23, 28],  # 缺失值 (NaN)
    '城市': ['北京', '上海', '广州', '深圳', '杭州', '北京'],
    '薪资': ['8000', '12000', '9500', 'N/A', '7000', '8000'],  # 有非数字字符串 'N/A'
    '入职日期': ['2020-01-15', '2019-05-20', '2021-08-01', '2018-11-30', '2022-03-10', '2020-01-15'],
    '评价': ['优秀', '良好', '优秀', '待改进', '良好', '优秀']
}
df = pd.DataFrame(data)

print("=== 原始数据 ===")
print(df)
print("\n")

# 1. 处理缺失值
# 查看缺失值情况
print("=== 各列缺失值数量 ===")
print(df.isnull().sum())
print("\n")

# 填充缺失值:用年龄列的均值填充
mean_age = df['年龄'].mean()
df['年龄'].fillna(mean_age, inplace=True)  # inplace=True 表示原地修改
# 或者使用 df['年龄'] = df['年龄'].fillna(mean_age)

# 2. 处理重复数据
# 查看是否有重复行
print("=== 标记重复行 (keep='first'保留第一处出现) ===")
print(df.duplicated())
print("\n")

# 删除完全重复的行(基于所有列)
df_cleaned = df.drop_duplicates()
print("=== 删除重复行后的数据 ===")
print(df_cleaned)
print("\n")

# 3. 数据类型转换与重命名
# 将'薪资'列转换为数值类型,忽略错误(将'N/A'等无效值转为NaN)
df_cleaned['薪资'] = pd.to_numeric(df_cleaned['薪资'], errors='coerce')

# 将'入职日期'列转换为datetime类型
df_cleaned['入职日期'] = pd.to_datetime(df_cleaned['入职日期'])

# 重命名列:将'姓名'改为'Name','年龄'改为'Age'
df_cleaned = df_cleaned.rename(columns={'姓名': 'Name', '年龄': 'Age'})

print("=== 类型转换与重命名后的数据信息 ===")
print(df_cleaned.dtypes)
print(df_cleaned)
print("\n")

# 4. 字符串操作
# 将'城市'列的所有值转换为小写
df_cleaned['城市小写'] = df_cleaned['城市'].str.lower()

# 检查'评价'列中是否包含'优'字
df_cleaned['是否优秀'] = df_cleaned['评价'].str.contains('优')

print("=== 字符串操作结果 ===")
print(df_cleaned[['Name', '城市', '城市小写', '评价', '是否优秀']])
print("\n")

# 5. 条件数据替换与筛选
# 将'评价'为'待改进'的员工,其'薪资'增加1000元作为激励
# 使用 .loc 进行条件赋值,避免链式索引警告
df_cleaned.loc[df_cleaned['评价'] == '待改进', '薪资'] = df_cleaned.loc[df_cleaned['评价'] == '待改进', '薪资'] + 1000

# 筛选出年龄大于30岁的员工
senior_employees = df_cleaned[df_cleaned['Age'] > 30]
print("=== 年龄大于30岁的员工 ===")
print(senior_employees[['Name', 'Age', '薪资']])

# 最终查看清洗后的完整数据
print("\n=== 最终清洗后的数据 ===")
print(df_cleaned)

运行结果预期:你将看到一个经过缺失值填充、去重、列重命名、类型转换、新增计算列,并根据条件修改了数据的清洁 DataFrame。

4. 实践练习

练习1:基础数据清洗 给定以下 DataFrame,请完成:

import pandas as pd
import numpy as np

exercise_data = {
    '产品': ['A', 'B', 'C', 'A', 'D', 'E'],
    '价格': [100, 200, np.nan, 100, 50, 150],
    '销量': [50, 30, 45, 50, '无数据', 60],
    '类别': ['电子', '家居', '电子', '电子', '食品', '家居']
}
df_ex = pd.DataFrame(exercise_data)

要求:

  1. 找出并删除完全重复的行。
  2. 将'销量'列转换为数值类型,无法转换的填充为 0
  3. 计算每行的'总销售额'(价格 * 销量)。

练习2:综合清洗与分析 使用下面更复杂的 DataFrame:

messy_data = {
    '员工ID': ['E001', 'E002', 'E003', 'E004', 'E001'],
    '姓名': ['alice', 'Bob Smith', 'Charlie', 'David', 'alice'],
    '部门': ['销售部', '市场部', '研发部', '销售部', '销售部'],
    '邮箱': ['[email protected]', 'bob.smith@co', '[email protected]', '[email protected]', '[email protected]'],
    '绩效分数': ['95', 'Good', '88', '91', '95']
}
df_messy = pd.DataFrame(messy_data)

要求:

  1. 删除重复的员工记录(基于'员工ID'和'姓名')。
  2. 将'姓名'列中的英文名转换为首字母大写(如 'alice' -> 'Alice', 'Bob Smith' -> 'Bob Smith')。
  3. 将'邮箱'列中不完整的邮箱(如不包含'@'或不以'.com'结尾)标记为'无效邮箱'。
  4. 将'绩效分数'列转换为数值,无法转换的(如'Good')用该列数值的均值填充。

5. 常见错误

  1. 直接删除缺失值而忽略业务逻辑:盲目使用 dropna() 可能会删除大量有价值的数据。应先分析缺失原因和占比,再决定策略。
  2. 忽略数据类型:将本应为数值的字符串列(如 '12,000')直接进行数学运算会导致错误。必须先进行类型转换和清理(如去除逗号)。
  3. 链式索引警告:使用 df[条件][列] = 值 这样的链式索引进行赋值可能会触发 SettingWithCopyWarning,并可能无法修改原 DataFrame。应使用 .loc.iloc
  4. 忘记使用 inplace=True 或赋值:很多 pandas 方法(如 fillna, rename)默认返回一个新对象,原地修改需要设置 inplace=True 或将结果赋值给原变量。
  5. 字符串方法误用.str.contains() 等方法区分大小写,如需不敏感匹配,可使用 case=False 参数。同时,操作对象必须是字符串类型。

6. 小结

本节课我们学习了 pandas 数据清洗与操作的核心技能:

  • 处理缺失值:使用 isnull(), fillna(), dropna() 来检查、填充或删除缺失数据。
  • 处理重复数据:使用 duplicated()drop_duplicates() 来识别和删除重复行。
  • 数据类型与格式:使用 astype(), pd.to_numeric(), pd.to_datetime() 转换类型;使用 rename() 修改列名。
  • 文本清洗:利用 .str 访问器进行批量字符串操作,如 .lower(), .contains(), .replace()
  • 条件操作:熟练使用布尔索引和 .loc 进行基于条件的筛选、赋值和修改。

掌握这些技能,你就能将杂乱的原始数据转变为结构清晰、可直接用于分析和建模的干净数据集,为后续的数据分析和可视化打下坚实基础。

练习编辑器

python
Loading...

继续学习

完成本课后,建议继续学习下一课「数据可视化:Matplotlib 基础」 以巩固所学知识。