
本教程旨在解决pandas dataframe中根据特定“键”列的值,对多列进行条件性映射和数据填充的问题。传统上,这可能涉及重复使用`numpy.select`,效率较低。文章将深入探讨两种高效的向量化方法:一是利用`pd.get_dummies`结合`df.mask`创建并应用布尔掩码;二是采用数据重塑技术,通过`melt`、`merge`和`unstack`实现。这些方法不仅提升了处理大规模数据的性能,也提高了代码的可读性和简洁性。
在数据处理和分析中,我们经常需要根据DataFrame中某一“键”列的值,有条件地更新或填充其他列的数据。例如,当“键”列为'key1'时,我们可能只关心'colA'和'colD'的值;当“键”列为'key2'时,只关心'colB'的值,而其他不相关的列则应被标记为'NA'。
原始的实现方式可能涉及为每个目标列独立调用numpy.select,这在大规模数据集或需要处理大量目标列时会显得冗余且效率低下。本教程将介绍两种更高效、更具向量化特性的方法来解决这一问题,以提升代码性能和可维护性。
我们将使用以下示例DataFrame作为演示:
import pandas as pd
import numpy as np
data = {
'key': ['key1', 'key2', 'key3', 'key1', 'key2'],
'colA': ['value1A', 'value2A', 'value3A', 'value4A', 'value5A'],
'colB': ['value1B', 'value2B', 'value3B', 'value4B', 'value5B'],
'colC': ['value1C', 'value2C', 'value3C', 'value4C', 'value5C'],
'colD': ['value1D', 'value2D', 'value3D', 'value4D', 'value5D']
}
df = pd.DataFrame(data)
print("原始DataFrame:")
print(df)输出:
原始DataFrame:
key colA colB colC colD
0 key1 value1A value1B value1C value1D
1 key2 value2A value2B value2C value2D
2 key3 value3A value3B value3C value3D
3 key1 value4A value4B value4C value4D
4 key2 value5A value5B value5C value5D我们的目标是根据key列的值,保留相应的列数据,并将其他不相关的列数据替换为'NA'。例如,对于key1行,colA和colD应保留,colB和colC应变为'NA'。
这种方法的核心思想是构建一个与DataFrame形状匹配的布尔掩码,该掩码指示哪些单元格应该保留其原始值,哪些应该被替换。然后,使用DataFrame.mask()方法根据这个掩码进行条件性替换。
定义映射关系: 首先,我们需要一个字典来定义每个key值对应哪些列是“有效”的。
d = {'key1': ['colA', 'colD'],
'key2':
['colB'],
'key3': ['colC']}生成布尔掩码: 这一步是关键。我们将利用pd.Series(d).explode()将字典展平,然后使用pd.get_dummies()将其转换为一个指示每个key对应哪些列的稀疏矩阵,最后通过groupby和max聚合,得到一个清晰的key到列的布尔映射。
s = pd.Series(d).explode() # s 示例: # key1 colA # key1 colD # key2 colB # key3 colC # dtype: object mask_template = pd.get_dummies(s, dtype=bool).groupby(level=0).max() # mask_template 示例: # colA colB colC colD # key1 True False False True # key2 False True False False # key3 False False True False
mask_template现在是一个索引为key值,列为目标列的布尔DataFrame,指示了每个key哪些列是有效的。
应用掩码到DataFrame: 我们需要将mask_template的布尔值扩展到与原始DataFrame的行数匹配。这可以通过reindex(df['key'])实现,然后将其转换为NumPy数组以与目标列进行操作。最后,使用df.mask()方法,其中mask=True的位置会被替换为指定值('NA'),mask=False的位置则保留原始值。
# 选择需要操作的列,排除'key'列
target_cols = df.columns.difference(['key'])
# 将mask_template与df['key']对齐,生成最终的行级布尔掩码
# .to_numpy() 转换为 NumPy 数组以提高性能,并确保与 df[target_cols] 的形状兼容
final_mask = mask_template.reindex(df['key']).to_numpy()
# 应用mask,当掩码为False时(即该单元格应该被替换时),将其替换为'NA'
# 注意:df.mask(cond, other) 在 cond 为 True 的地方替换为 other
# 所以我们需要的是 mask_template 为 True 的地方保留,False 的地方替换。
# 而 df.mask 的行为是 True 替换,False 保留。
# 因此,我们实际上需要的是 !final_mask 作为 mask 的条件,或者使用 df.where(final_mask, 'NA')
# 这里我们使用 df.where,其行为是 True 保留,False 替换。
df[target_cols] = df[target_cols].where(final_mask, 'NA')
print("\n方法一结果:")
print(df)最终输出:
方法一结果:
key colA colB colC colD
0 key1 value1A NA NA value1D
1 key2 NA value2B NA NA
2 key3 NA NA value3C NA
3 key1 value4A NA NA value4D
4 key2 NA value5B NA NA优点:
Motiff妙多
Motiff妙多是一款AI驱动的界面设计工具,定位为“AI时代设计工具”
334
查看详情
这种方法通过将DataFrame重塑为“长格式”,与映射关系进行合并,然后再次重塑回“宽格式”来实现条件映射。这种方法在处理更复杂的数据转换逻辑时也具有很高的灵活性。
定义映射关系: 与方法一相同,首先定义key到列的映射字典。
d = {'key1': ['colA', 'colD'],
'key2': ['colB'],
'key3': ['colC']}重塑DataFrame到长格式 (melt): 将原始DataFrame转换为长格式,其中所有目标列的值都集中在一个value列中,对应的列名在variable列中。我们保留原始索引和key列作为标识符。
df_melted = df.reset_index().melt(id_vars=['index', 'key']) # df_melted 示例(部分): # index key variable value # 0 0 key1 colA value1A # 1 1 key2 colA value2A # 2 2 key3 colA value3A # ...
准备映射关系为DataFrame: 将字典d也转换为长格式DataFrame,以便与df_melted进行合并。
mapping_df = pd.Series(d).explode().rename_axis('key').reset_index(name='variable')
# mapping_df 示例:
# key variable
# 0 key1 colA
# 1 key1 colD
# 2 key2 colB
# 3 key3 colC合并并筛选有效数据 (merge): 通过inner merge操作,我们只保留df_melted中那些key和variable组合在mapping_df中存在的行。这意味着只有符合条件的(即应该保留的)数据才会被保留下来。
merged_df = df_melted.merge(mapping_df, on=['key', 'variable'], how='inner') # merged_df 示例(部分): # index key variable value # 0 0 key1 colA value1A # 1 3 key1 colA value4A # 2 0 key1 colD value1D # ...
重塑回宽格式并填充缺失值 (unstack): 最后,我们将merged_df再次重塑回宽格式。set_index用于设置新的索引,unstack('variable')将variable列的值转换为新的列名。在此过程中,由于merge操作移除了不符合条件的数据,因此在unstack时这些位置将是缺失的,我们可以使用fill_value='NA'来填充它们。
final_df = (merged_df
.set_index(['index', 'key', 'variable'])['value']
.unstack('variable', fill_value='NA')
.reset_index('key')
.rename_axis(index=None, columns=None))
# 重新将'key'列放回原位(如果需要,或者根据实际需求调整列顺序)
# 确保原始的非目标列(本例中只有'key')也在最终结果中
# 鉴于我们的目标是替换原始df的列,我们可以直接赋值
df_result = df[['key']].copy() # 保留原始key列
# 将处理后的结果与原始df的key列合并
df_result = df_result.merge(final_df, left_index=True, right_index=True, how='left')
# 调整列顺序,确保'key'在最前面
df_result = df_result[['key'] + [col for col in final_df.columns if col != 'key']]
print("\n方法二结果:")
print(df_result)最终输出:
方法二结果:
key colA colB colC colD
0 key1 value1A NA NA value1D
1 key2 NA value2B NA NA
2 key3 NA NA value3C NA
3 key1 value4A NA NA value4D
4 key2 NA value5B NA NA优点:
两种方法都有效地解决了根据“键”列条件性映射多列数据的问题,并且都采用了向量化操作,避免了低效的行级迭代。
pd.get_dummies + df.mask (或 df.where):
melt + merge + unstack:
在选择方法时,请根据你的具体需求、数据集大小以及个人偏好进行权衡。对于大多数简单的条件映射任务,get_dummies和mask组合通常是更直接和高效的选择。而当涉及到更复杂的数据关系和转换时,melt/merge/unstack模式则提供了更大的灵活性。始终优先考虑使用Pandas和NumPy提供的向量化操作,以确保代码的高性能和可扩展性。
以上就是基于键列高效映射Pandas DataFrame多列数据教程的详细内容,更多请关注其它相关文章!
相关文章:
斑马英语APP如何开启夜间护眼阅读_斑马英语APP夜间模式与低蓝光设置教程
单12V-2×6实现为RTX 5090供电750W!甚至都没敢跑分
使用Python高效删除Word宏并转换DOCM为DOCX格式
PHP表单提交消息延迟显示:Post-Redirect-Get模式深度解析与实践
QQ邮箱网页版入口 QQ邮箱官方邮箱登录通道
大麦的“候补”是什么意思 大麦候补购票规则【详解】
高德地图公交到站提醒失败如何解决 高德提醒权限设置
J*a递归快速排序中静态变量的状态管理与陷阱
mc.js游戏直达 mc.js网页免下载版本秒进地址
响应式图片在网页设计中的正确实现方法
mysql如何分析事务日志_mysql事务日志分析方法
Yii2模块参数配置指南:正确声明与访问模块级配置
高德地图总提示网络异常怎么办 高德地图离线导航设置与网络排查方法
Go语言中动态执行代码字符串的策略与实践
可靠CSGO开箱平台解析 CSGO开箱网合集
如何使用CaptainHook和Composer管理Git钩子_在提交前自动运行代码检查的Composer配置
荣耀Play7T运行卡顿解决_荣耀Play7T性能优化
《噬血代码2》新预告片发布 展示游戏剧情
Composer如何在生产环境安全地执行composer update
msn官网入口地址手机版 msn官方网站手机最新链接
漫蛙2(台版)官方入口地址 漫蛙2(台版)正版漫画网页端
提升屏幕阅读器对“m”时间单位的播报准确性:HTML与CSS组合解决方案
J*aScript实现动态背景色下的文本与按钮颜色自适应调整
荣耀Play7TPro怎样在信息App置顶客服对话_iPhone荣耀Play7TPro信息App置顶客服对话【优先查看】
Golang如何测试channel通信行为_Golang channel通信测试与分析方法
CSS Box Model与弹性按钮:维持布局稳定的动画实践
CSS布局:解决全屏元素100%尺寸与外边距导致的页面溢出问题
葱吃多了会怎样 葱吃多了会伤胃吗
淘宝网网页版登录入口 淘宝官方网页版快捷登录
哔哩哔哩忘记密码了怎么找回_哔哩哔哩密码找回方法
PDF文件体积过大处理_PDF压缩技巧详解
KFC套餐升级怎么获取优惠代码_KFC套餐升级活动与优惠代码获取方法
Angular Material 垂直步进器:实现底部到顶部排序的教程
J*aScript井字棋(Tic-Tac-Toe)核心交互逻辑实现教程
Golang如何实现Web文件静态资源服务器_Golang静态资源服务器开发与实践
steam官方入口大全 steam账号注册及操作指南
word中如何让数字纵向排列_Word数字纵向排列方法
如何在CSS中使用浮动制作导航栏_float实现水平菜单
c++如何实现一个简单的ECS框架_c++数据驱动设计与游戏开发
mcjs网页版在线存档 mcjs云存档登录入口
Golang如何实现简单的Web表单_Golang表单提交与验证处理方法
MongoDB Aggregation:在嵌套对象数组中精确匹配ObjectId
c++如何使用TBB库进行任务并行_c++ Intel线程构建模块
一加 Nord 5 隐私权限异常_一加 Nord 5 系统安全优化
三星GalaxyZFold5怎样在相册制作折叠屏分镜_iPhone三星GalaxyZFold5相册制作折叠屏分镜【创意编辑】
抓大鹅无需下载版 抓大鹅秒玩版入口
抖音小游戏合成大西瓜免费秒玩入口链接 抖音小游戏热门合集秒玩网站
2025-2030年全球乘用车销量预测:新能源成增长主力
在J*a中如何使用BigDecimal进行高精度计算_BigDecimal类应用指南
如何在Python中使用Optional类型处理可变对象并避免Pylint警告