0

0

Pandas数据处理:补齐分组数据中缺失的行

碧海醫心

碧海醫心

发布时间:2025-09-15 10:53:46

|

386人浏览过

|

来源于php中文网

原创

Pandas数据处理:补齐分组数据中缺失的行

本教程旨在解决Pandas数据处理中,确保每个分组(如按姓名分组)都包含预定义的所有类型(如CA, DA等)的问题。通过结合使用drop_duplicates、merge(how='cross')和merge(how='left'),我们可以生成所有可能的组合,然后将原始数据合并到此模板上,并用指定值(如0)填充缺失项,从而高效地补齐数据,确保数据完整性。

问题描述

在数据分析和报表生成过程中,我们经常会遇到这样的需求:给定一个数据集,其中包含按某些关键字段(如“姓名”、“部门”)分组的数据,并且每个分组应包含一个预定义的所有可能“类型”的完整集合。然而,原始数据可能由于各种原因导致某些分组缺少特定“类型”的行。例如,在一个销售数据集中,我们希望确保每个销售员(按姓名分组)都包含所有产品类别(“类型”),即使某个销售员在某个类别下没有销售记录。对于这些缺失的行,我们通常需要创建它们,并用默认值(如0)填充其数值列,以保证数据结构的完整性和后续分析的准确性。

考虑以下示例数据:

import pandas as pd

data = {
    'First Name': ['Alice', 'Alice', 'Alice', 'Alice', 'Bob', 'Bob'],
    'Last Name': ['Johnson', 'Johnson', 'Johnson', 'Johnson', 'Jack', 'Jack'],
    'Type': ['CA', 'DA', 'FA', 'GCA', 'CA', 'GCA'],
    'Value': [25, 30, 35, 40, 50, 37]
}

# 定义所有可能的类型列表
types = ['CA', 'DA', 'FA', 'GCA']
df = pd.DataFrame(data)

print("原始DataFrame:")
print(df)

在这个例子中,我们希望每个“First Name”和“Last Name”的组合(即每个独立的人)都拥有 types 列表中定义的所有四种“Type”类型。观察数据,Alice Johnson 已经拥有所有四种类型,但 Bob Jack 仅有 CA 和 GCA 两种类型,缺少 DA 和 FA。我们的目标是为 Bob Jack 创建两条新行,分别对应 DA 和 FA 类型,并将它们的 Value 列设置为0。

解决方案

解决此问题的核心思路是构建一个包含所有分组键与所有可能类型组合的“模板”DataFrame,然后将原始数据左连接到这个模板上。这样,模板中存在但在原始数据中缺失的组合将会在连接后产生 NaN 值,我们随后可以填充这些 NaN 值。

以下是具体的实现步骤和代码:

BlackBox AI
BlackBox AI

AI编程助手,智能对话问答助手

下载
  1. 提取唯一的组合键: 从原始DataFrame中提取用于分组的唯一键(例如“First Name”和“Last Name”的组合)。
  2. 生成所有类型组合: 将这些唯一的组合键与预定义的所有“Type”列表进行交叉合并(笛卡尔积),生成一个包含所有可能组合的完整模板。
  3. 左连接原始数据: 将这个完整的模板与原始DataFrame进行左连接。连接键应包括所有分组键和“Type”列。由于是左连接,模板中的所有行都将被保留,而原始数据中不存在的组合将导致 Value 列出现 NaN。
  4. 填充缺失值: 使用 fillna(0) 将 Value 列中的 NaN 值替换为0。
  5. 数据类型转换(可选): fillna 操作可能会将整数列转换为浮点数列(因为 NaN 是浮点类型)。如果需要,可以将 Value 列转换回整数类型。
# 解决方案代码
out = (df[['First Name', 'Last Name']]  # 1. 提取唯一的组合键
    .drop_duplicates()  # 确保每个组合键只出现一次
    .merge(pd.Series(types, name='Type'), how='cross')  # 2. 与所有类型进行交叉合并,生成模板
    .merge(df, on=['First Name', 'Last Name', 'Type'], how='left')  # 3. 左连接原始DataFrame
    .fillna(0)  # 4. 填充缺失值(NaN)为0
    # 5. 可选:将'Value'列转换回整数类型,因为fillna可能导致其变为浮点型
    .astype({'Value': int})
)

print("\n补齐后的DataFrame:")
print(out)

代码解析

  • df[['First Name', 'Last Name']].drop_duplicates(): 这一步首先从原始DataFrame中选择“First Name”和“Last Name”两列,然后使用 drop_duplicates() 方法获取所有不重复的姓名组合。这构成了我们分组的唯一标识。
  • .merge(pd.Series(types, name='Type'), how='cross'): 接下来,我们将上一步得到的唯一姓名组合与 types 列表(通过 pd.Series 转换为一个DataFrame列)进行交叉合并。how='cross' 参数执行笛卡尔积,生成了所有姓名与所有类型的组合。例如,如果 Alice Johnson 是一个唯一的姓名组合,它将与 CA, DA, FA, GCA 各自组合,形成四行。
  • .merge(df, on=['First Name', 'Last Name', 'Type'], how='left'): 这一步是关键。我们将上一步生成的包含所有可能组合的模板DataFrame与原始 df 进行左连接。连接键是 ['First Name', 'Last Name', 'Type']。这意味着,如果模板中的某个组合(如 Bob Jack, DA)在原始 df 中不存在,那么连接后的 Value 列将为 NaN。
  • .fillna(0): 在左连接后,所有因为原始数据中缺失而产生的 NaN 值都会被 0 填充。
  • .astype({'Value': int}): 由于 NaN 是浮点类型,当 Value 列中出现 NaN 时,整个列的数据类型会自动提升为浮点型。如果希望 Value 列保持整数类型,则需要在此处显式地将其转换回 int。

输出结果

执行上述代码后,我们将得到如下的DataFrame:

  First Name Last Name Type  Value
0      Alice   Johnson   CA     25
1      Alice   Johnson   DA     30
2      Alice   Johnson   FA     35
3      Alice   Johnson  GCA     40
4        Bob      Jack   CA     50
5        Bob      Jack   DA      0
6        Bob      Jack   FA      0
7        Bob      Jack  GCA     37

可以看到,Bob Jack 组合现在包含了 DA 和 FA 两种类型,并且它们的 Value 列已成功填充为0,从而满足了我们的需求。

注意事项与总结

  • 性能考量: how='cross' 操作会生成笛卡尔积,如果分组键的数量或 types 列表的长度非常大,可能会导致生成的中间DataFrame非常庞大,占用大量内存并影响性能。在处理大规模数据时,需要评估其可行性。
  • 数据类型转换: 填充 NaN 值时,如果目标列原为整数类型,Pandas会自动将其转换为浮点类型。如果需要保持整数类型,务必在 fillna 之后进行 astype(int) 转换。
  • 灵活性: 这种方法非常灵活,可以应用于任何需要补齐分组数据中缺失组合的场景,只需调整分组键和预定义的类型列表即可。
  • 默认值选择: fillna() 中的默认值可以根据实际业务需求进行调整,不限于0。例如,可以填充为平均值、中位数或空字符串等。

通过这种组合使用 drop_duplicates、merge(how='cross') 和 merge(how='left') 的策略,我们能够高效且优雅地解决Pandas中补齐分组数据缺失行的问题,确保数据完整性和一致性,为后续的数据分析和建模奠定坚实基础。

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

相关专题

更多
Python 时间序列分析与预测
Python 时间序列分析与预测

本专题专注讲解 Python 在时间序列数据处理与预测建模中的实战技巧,涵盖时间索引处理、周期性与趋势分解、平稳性检测、ARIMA/SARIMA 模型构建、预测误差评估,以及基于实际业务场景的时间序列项目实操,帮助学习者掌握从数据预处理到模型预测的完整时序分析能力。

51

2025.12.04

数据类型有哪几种
数据类型有哪几种

数据类型有整型、浮点型、字符型、字符串型、布尔型、数组、结构体和枚举等。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

301

2023.10.31

php数据类型
php数据类型

本专题整合了php数据类型相关内容,阅读专题下面的文章了解更多详细内容。

222

2025.10.31

js 字符串转数组
js 字符串转数组

js字符串转数组的方法:1、使用“split()”方法;2、使用“Array.from()”方法;3、使用for循环遍历;4、使用“Array.split()”方法。本专题为大家提供js字符串转数组的相关的文章、下载、课程内容,供大家免费下载体验。

256

2023.08.03

js截取字符串的方法
js截取字符串的方法

js截取字符串的方法有substring()方法、substr()方法、slice()方法、split()方法和slice()方法。本专题为大家提供字符串相关的文章、下载、课程内容,供大家免费下载体验。

208

2023.09.04

java基础知识汇总
java基础知识汇总

java基础知识有Java的历史和特点、Java的开发环境、Java的基本数据类型、变量和常量、运算符和表达式、控制语句、数组和字符串等等知识点。想要知道更多关于java基础知识的朋友,请阅读本专题下面的的有关文章,欢迎大家来php中文网学习。

1465

2023.10.24

字符串介绍
字符串介绍

字符串是一种数据类型,它可以是任何文本,包括字母、数字、符号等。字符串可以由不同的字符组成,例如空格、标点符号、数字等。在编程中,字符串通常用引号括起来,如单引号、双引号或反引号。想了解更多字符串的相关内容,可以阅读本专题下面的文章。

619

2023.11.24

java读取文件转成字符串的方法
java读取文件转成字符串的方法

Java8引入了新的文件I/O API,使用java.nio.file.Files类读取文件内容更加方便。对于较旧版本的Java,可以使用java.io.FileReader和java.io.BufferedReader来读取文件。在这些方法中,你需要将文件路径替换为你的实际文件路径,并且可能需要处理可能的IOException异常。想了解更多java的相关内容,可以阅读本专题下面的文章。

550

2024.03.22

Golang gRPC 服务开发与Protobuf实战
Golang gRPC 服务开发与Protobuf实战

本专题系统讲解 Golang 在 gRPC 服务开发中的完整实践,涵盖 Protobuf 定义与代码生成、gRPC 服务端与客户端实现、流式 RPC(Unary/Server/Client/Bidirectional)、错误处理、拦截器、中间件以及与 HTTP/REST 的对接方案。通过实际案例,帮助学习者掌握 使用 Go 构建高性能、强类型、可扩展的 RPC 服务体系,适用于微服务与内部系统通信场景。

8

2026.01.15

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号