Pandas DataFrame 实战分析:分组、合并、查询、索引与缺失值处理

13 阅读7分钟

Pandas DataFrame 实战分析:分组、合并、查询、索引与缺失值处理

Pandas 是 Python 数据分析的基石,DataFrame 作为其核心数据结构,提供了强大的数据处理能力。本文将通过实战案例,详细分析 DataFrame 在分组合并查询重建索引缺失值填充索引对象方面的应用,并提供代码示例和记忆技巧,帮助你深入掌握这些功能。


一、分组实战(GroupBy)

1. 功能简介

分组操作通过 groupby() 方法实现,用于按某列(或多列)将数据分组,然后对每组应用聚合函数(如求和、均值)或自定义操作。

2. 实战案例

假设有一个学生成绩表,分析每个班级的平均成绩。

import pandas as pd

# 创建 DataFrame
data = {
    'class': ['A', 'A', 'B', 'B', 'C'],
    'student': ['Alice', 'Bob', 'Cathy', 'David', 'Eve'],
    'score': [90, 85, 88, 92, 95]
}
df = pd.DataFrame(data)

# 分组并计算每个班级的平均成绩
class_avg = df.groupby('class')['score'].mean()
print(class_avg)
# 输出:
# class
# A    87.5
# B    90.0
# C    95.0
# Name: score, dtype: float64

# 多列分组:按班级和学生统计
group = df.groupby('class').agg({'score': ['mean', 'max']})
print(group)
# 输出:
#        score      
#         mean max
# class           
# A       87.5  90
# B       90.0  92
# C       95.0  95

3. 关键点

  • 分组依据:可以是单列(df.groupby('class'))或多列(df.groupby(['class', 'student']))。
  • 聚合函数:常用 mean(), sum(), count(), max() 等,也支持自定义函数通过 apply()
  • 多列聚合:使用 agg() 可对不同列应用不同函数。

4. 记忆技巧

groupby() 想象为“按标签打包”,每一组是一个“包裹”,然后对每个包裹执行统计操作。


二、合并实战(Merge)

1. 功能简介

merge() 用于合并两个 DataFrame,类似于 SQL 的 JOIN 操作,支持内连接、左连接、右连接和外连接。

2. 实战案例

假设有学生信息表和成绩表,合并它们以获取完整信息。

# 学生信息表
df1 = pd.DataFrame({
    'student_id': [1, 2, 3, 4],
    'name': ['Alice', 'Bob', 'Cathy', 'David']
})

# 成绩表
df2 = pd.DataFrame({
    'student_id': [1, 2, 3, 5],
    'score': [90, 85, 88, 92]
})

# 内连接:只保留匹配的记录
merged_inner = pd.merge(df1, df2, on='student_id', how='inner')
print(merged_inner)
# 输出:
#    student_id   name  score
# 0           1  Alice     90
# 1           2    Bob     85
# 2           3  Cathy     88

# 左连接:保留 df1 的所有记录
merged_left = pd.merge(df1, df2, on='student_id', how='left')
print(merged_left)
# 输出:
#    student_id   name  score
# 0           1  Alice   90.0
# 1           2    Bob   85.0
# 2           3  Cathy   88.0
# 3           4  David    NaN

3. 关键点

  • 参数

    • on:指定合并的键(列名)。
    • how:连接类型(inner, left, right, outer)。
    • left_on / right_on:当键名不同时使用。
  • 性能:对于大数据集,合并前确保键列的数据类型一致以提升效率。

4. 记忆技巧

merge() 想象为“两张表格拼图”,on 是拼图的连接点,how 决定如何处理不匹配的部分。


三、查询实战

1. 功能简介

查询操作通过条件筛选、布尔索引或 query() 方法提取满足条件的行。

2. 实战案例

筛选成绩高于 90 的学生,并查询特定班级的记录。

# 数据
df = pd.DataFrame({
    'class': ['A', 'A', 'B', 'B', 'C'],
    'student': ['Alice', 'Bob', 'Cathy', 'David', 'Eve'],
    'score': [90, 85, 88, 92, 95]
})

# 布尔索引:筛选 score > 90
high_score = df[df['score'] > 90]
print(high_score)
# 输出:
#   class student  score
# 3     B  David     92
# 4     C    Eve     95

# query() 方法:筛选 class == 'A' 且 score >= 85
class_a = df.query("class == 'A' and score >= 85")
print(class_a)
# 输出:
#   class student  score
# 0     A  Alice     90
# 1     A    Bob     85

3. 关键点

  • 布尔索引:使用条件表达式(如 df['score'] > 90)生成布尔 Series。
  • query() :支持 SQL 风格的字符串查询,适合复杂条件。
  • 性能query() 在大数据集上通常比布尔索引快。

4. 记忆技巧

将查询想象为“从表格中挑出符合规则的行”,布尔索引是“手工筛选”,query() 是“自动化过滤”。


四、重建索引实战(Reindex)

1. 功能简介

reindex() 用于更改 DataFrame 的行或列索引,可以重新排序、添加或删除索引。

2. 实战案例

调整 DataFrame 的行索引,并为缺失的索引填充值。

# 数据
df = pd.DataFrame({
    'name': ['Alice', 'Bob', 'Cathy'],
    'score': [90, 85, 88]
}, index=['x', 'y', 'z'])

# 重新设置行索引
df_reindexed = df.reindex(['w', 'x', 'y', 'z', 'a'])
print(df_reindexed)
# 输出:
#    name  score
# w   NaN    NaN
# x  Alice   90.0
# y    Bob   85.0
# z  Cathy   88.0
# a   NaN    NaN

# 填充缺失值
df_filled = df.reindex(['w', 'x', 'y', 'z', 'a'], fill_value=0)
print(df_filled)
# 输出:
#    name  score
# w     0      0
# x  Alice     90
# y    Bob     85
# z  Cathy     88
# a     0      0

3. 关键点

  • 参数

    • index:新行索引。
    • columns:新列索引。
    • fill_value:填充缺失值。
  • 用途:常用于数据对齐或统一索引格式。

4. 记忆技巧

reindex() 想象为“重新贴标签”,新标签可能导致空位(NaN),需要决定是否填充。


五、缺失值填充实战(Handling Missing Values)

1. 功能简介

缺失值(NaN 或 None)在数据分析中常见,Pandas 提供多种方法处理缺失值,包括删除(dropna())和填充(fillna())。

2. 实战案例

以下分析不同场景下的缺失值处理。

(1)删除缺失值
# 数据
df = pd.DataFrame({
    'name': ['Alice', 'Bob', None, 'David'],
    'score': [90, None, 88, 92]
})

# 删除包含缺失值的行
df_dropped = df.dropna()
print(df_dropped)
# 输出:
#     name  score
# 0  Alice   90.0
# 3  David   92.0
(2)填充固定值
# 填充 NaN 为 0
df_filled = df.fillna(0)
print(df_filled)
# 输出:
#     name  score
# 0  Alice   90.0
# 1    Bob    0.0
# 2      0   88.0
# 3  David   92.0
(3)前向填充(ffill)/后向填充(bfill)
# 前向填充:用前一个值填充
df_ffill = df.fillna(method='ffill')
print(df_ffill)
# 输出:
#     name  score
# 0  Alice   90.0
# 1    Bob   90.0
# 2    Bob   88.0
# 3  David   92.0
(4)按列填充不同值
# 按列指定填充值
df_col_fill = df.fillna({'name': 'Unknown', 'score': df['score'].mean()})
print(df_col_fill)
# 输出:
#      name      score
# 0   Alice  90.000000
# 1     Bob  90.000000
# 2  Unknown  88.000000
# 3   David  92.000000
(5)插值填充(interpolate)
# 线性插值
df_interpolate = df['score'].interpolate()
print(df_interpolate)
# 输出:
# 0    90.0
# 1    89.0
# 2    88.0
# 3    92.0
# Name: score, dtype: float64

3. 关键点

  • 删除dropna() 适合缺失值较少的情况,避免丢失过多数据。

  • 填充

    • 固定值:简单但可能引入偏差。
    • 前/后向填充:适合时间序列数据。
    • 均值/中位数:适合数值列,保留分布特性。
    • 插值:适合连续数据,生成平滑过渡值。
  • 注意:填充前需分析数据分布,避免引入不合理值。

4. 记忆技巧

将缺失值处理想象为“修补破洞的衣服”:

  • 删除:直接扔掉破损部分(dropna())。
  • 填充:用布料补洞(fillna()),布料可以是固定颜色(固定值)、附近颜色(ffill/bfill)或渐变色(interpolate)。

六、索引对象实战(Index Objects)

1. 功能简介

Pandas 的索引对象(Index 或其子类)管理行和列的标签,支持高效查询和对齐。

2. 实战案例

操作索引对象,修改和查询索引。

# 数据
df = pd.DataFrame({
    'name': ['Alice', 'Bob', 'Cathy'],
    'score': [90, 85, 88]
}, index=['x', 'y', 'z'])

# 获取索引
print(df.index)
# 输出:Index(['x', 'y', 'z'], dtype='object')

# 修改索引
df.index = ['a', 'b', 'c']
print(df)
# 输出:
#     name  score
# a  Alice     90
# b    Bob     85
# c  Cathy     88

# 检查索引是否存在
print('a' in df.index)  # True

# 重置索引为默认整数索引
df_reset = df.reset_index(drop=True)
print(df_reset)
# 输出:
#     name  score
# 0  Alice     90
# 1    Bob     85
# 2  Cathy     88

# 设置某列为索引
df_set = df.set_index('name')
print(df_set)
# 输出:
#        score
# name       
# Alice     90
# Bob       85
# Cathy     88

3. 关键点

  • 索引类型:常见有 Index(通用)、RangeIndex(整数序列)、MultiIndex(多级索引)。

  • 操作

    • reset_index():将索引转为列或丢弃。
    • set_index():将列设为索引。
  • 不可变性:索引对象是不可变的,保证数据一致性。

4. 记忆技巧

将索引对象想象为“表格的门牌号”,可以更换(set_index)、重置(reset_index),但门牌本身不能随意修改。


七、总结与记忆技巧

1. 综合记忆

  • 分组:像整理书架,按类别(groupby)整理后再统计。
  • 合并:像拼图,找共同点(on)拼接表格。
  • 查询:像搜索,设定条件(布尔或 query)找到目标。
  • 重建索引:像重新贴标签,调整表格的“地址”。
  • 缺失值:像修补漏洞,选择合适的“材料”填充。
  • 索引对象:像门牌号,管理表格的定位系统。

2. 实践建议

  • 动手实践:运行每个案例代码,尝试修改参数(如 howmethod)观察效果。
  • 真实数据:找一个 CSV 文件(如 Kaggle 数据集),应用这些操作。
  • 记录笔记:将常用方法(如 groupby, merge)整理成 cheatsheet。

通过本文的实战案例,你可以更深入理解 Pandas DataFrame 的核心功能。希望这篇博客能帮助你快速上手 Pandas 并在数据分析中游刃有余!