基于键列高效映射Pandas DataFrame多列数据教程

基于键列高效映射Pandas DataFrame多列数据教程

本教程旨在解决pandas dataframe中根据特定“键”列的值,对多列进行条件性映射和数据填充的问题。传统上,这可能涉及重复使用`numpy.select`,效率较低。文章将深入探讨两种高效的向量化方法:一是利用`pd.get_dummies`结合`df.mask`创建并应用布尔掩码;二是采用数据重塑技术,通过`melt`、`merge`和`unstack`实现。这些方法不仅提升了处理大规模数据的性能,也提高了代码的可读性和简洁性。

Pandas DataFrame多列条件映射的优化策略

在数据处理和分析中,我们经常需要根据DataFrame中某一“键”列的值,有条件地更新或填充其他列的数据。例如,当“键”列为’key1’时,我们可能只关心’colA’和’colD’的值;当“键”列为’key2’时,只关心’colB’的值,而其他不相关的列则应被标记为’NA’。

原始的实现方式可能涉及为每个目标列独立调用numpy.select,这在大规模数据集或需要处理大量目标列时会显得冗余且效率低下。本教程将介绍两种更高效、更具向量化特性的方法来解决这一问题,以提升代码性能和可维护性。

我们将使用以下示例DataFrame作为演示:

import pandas as pdimport numpy as npdata = {    '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     colD0  key1  value1A  value1B  value1C  value1D1  key2  value2A  value2B  value2C  value2D2  key3  value3A  value3B  value3C  value3D3  key1  value4A  value4B  value4C  value4D4  key2  value5A  value5B  value5C  value5D

我们的目标是根据key列的值,保留相应的列数据,并将其他不相关的列数据替换为’NA’。例如,对于key1行,colA和colD应保留,colB和colC应变为’NA’。

方法一:利用布尔掩码 (pd.get_dummies 和 df.mask)

这种方法的核心思想是构建一个与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: objectmask_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     colD0  key1  value1A       NA       NA  value1D1  key2       NA  value2B       NA       NA2  key3       NA       NA  value3C       NA3  key1  value4A       NA       NA  value4D4  key2       NA  value5B       NA       NA

优点:

Stable Diffusion 2.1 Demo Stable Diffusion 2.1 Demo

最新体验版 Stable Diffusion 2.1

Stable Diffusion 2.1 Demo 101 查看详情 Stable Diffusion 2.1 Demo 高度向量化,适用于大型数据集。逻辑清晰,通过布尔掩码直观地控制数据保留与替换。

方法二:数据重塑 (melt, merge, unstack)

这种方法通过将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     colD0  key1  value1A       NA       NA  value1D1  key2       NA  value2B       NA       NA2  key3       NA       NA  value3C       NA3  key1  value4A       NA       NA  value4D4  key2       NA  value5B       NA       NA

优点:

对于复杂的条件逻辑和数据转换场景,melt/merge/unstack模式非常强大。整个过程都是向量化的,避免了显式循环。易于扩展,例如,如果需要根据多个键列进行映射,此方法也能很好地适应。

总结与注意事项

两种方法都有效地解决了根据“键”列条件性映射多列数据的问题,并且都采用了向量化操作,避免了低效的行级迭代。

pd.get_dummies + df.mask (或 df.where):

优点: 代码相对简洁,直观地构建布尔掩码,对于纯粹的条件替换场景非常高效。适用场景: 当你只需要根据键列的值来决定哪些单元格保留,哪些单元格替换为固定值时。

melt + merge + unstack:

优点: 灵活性高,不仅可以用于条件替换,还可以用于更复杂的数据聚合、转换和过滤。中间步骤清晰,便于调试。适用场景: 当你需要进行更复杂的数据转换,或者需要将外部映射数据与DataFrame进行灵活组合时。虽然代码行数可能稍多,但其强大的通用性使其成为处理复杂数据转换的有力工具

在选择方法时,请根据你的具体需求、数据集大小以及个人偏好进行权衡。对于大多数简单的条件映射任务,get_dummies和mask组合通常是更直接和高效的选择。而当涉及到更复杂的数据关系和转换时,melt/merge/unstack模式则提供了更大的灵活性。始终优先考虑使用Pandas和NumPy提供的向量化操作,以确保代码的高性能和可扩展性。

以上就是基于键列高效映射Pandas DataFrame多列数据教程的详细内容,更多请关注创想鸟其它相关文章!

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 chuangxiangniao@163.com 举报,一经查实,本站将立刻删除。
发布者:程序猿,转转请注明出处:https://www.chuangxiangniao.com/p/905409.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
51动漫网入口地址 51动漫网正版在线入口
上一篇 2025年11月28日 22:48:31
opporeno9的优缺点?
下一篇 2025年11月28日 22:48:36

相关推荐

  • composer require-dev和require有什么不同_Composer Require与Require-Dev区别解析

    require用于声明项目运行必需的依赖,如框架、数据库组件和第三方SDK,这些包会随项目部署到生产环境;2. require-dev用于声明仅在开发和测试阶段需要的工具,如PHPUnit、PHPStan、Faker等,不会默认部署到生产环境;3. 安装时composer install根据环境决定…

    2026年5月10日
    1000
  • Matplotlib 地图中多类型图例的创建与优化

    Matplotlib 地图中多类型图例的创建与优化Matplotlib 地图中多类型图例的创建与优化Matplotlib 地图中多类型图例的创建与优化Matplotlib 地图中多类型图例的创建与优化

    本教程旨在解决matplotlib地图可视化中,如何在一个图例中同时展示颜色块(如区域分类)和自定义标记(如特定兴趣点)的问题。文章详细介绍了当传统`patch`对象无法正确显示标记时,如何利用`matplotlib.lines.line2d`创建标记图例句柄,并将其与颜色块图例句柄合并,从而生成一…

    2026年5月10日 用户投稿
    100
  • 利用海象运算符简化条件赋值:Python教程与最佳实践

    本文旨在探讨Python中海象运算符(:=)在条件赋值场景下的应用。通过对比传统if/else语句与海象运算符,以及条件表达式,分析海象运算符在简化代码、提高可读性方面的优势与局限性。并通过具体示例,展示如何在列表推导式等场景下合理使用海象运算符,同时强调其潜在的复杂性及替代方案,帮助开发者更好地掌…

    2026年5月10日
    100
  • Debian syslog性能优化技巧有哪些

    提升Debian系统syslog (通常基于rsyslog)性能,关键在于精简配置和高效处理日志。以下策略能有效优化日志管理,提升系统整体性能: 精简配置,高效加载: 在rsyslog配置文件中,仅加载必要的输入、输出和解析模块。 使用全局指令设置日志级别和格式,避免不必要的处理。 自定义模板: 创…

    2026年5月10日
    000
  • 比特币新手教程 比特币交易平台有哪些

    比特币是一种去中心化的数字货币,基于区块链技术实现点对点交易,具有匿名性、有限发行和不可篡改等特点;新手可通过交易所购买,P2P交易获得比特币,常用平台包括Binance、OKX和Huobi;交易流程包括注册账户、实名认证、绑定支付方式、充值法币并下单购买,可选择市价单或限价单;比特币存储方式有交易…

    2026年5月10日
    000
  • c++中的SFINAE技术是什么_c++模板编程中的SFINAE原理与应用

    SFINAE 是“替换失败不是错误”的原则,指模板实例化时若参数替换导致错误,只要存在其他合法候选,编译器不报错而是继续重载决议。它用于条件启用模板、类型检测等场景,如通过 decltype 或 enable_if 控制函数重载,实现类型特征判断。尽管 C++20 引入 Concepts 简化了部分…

    2026年5月10日
    000
  • Golang goroutine与channel调试技巧

    使用go run -race检测数据竞争,结合runtime.NumGoroutine监控协程数量,通过pprof分析阻塞调用栈,利用select超时避免永久阻塞,有效排查goroutine泄漏、死锁和数据竞争问题。 Go语言的goroutine和channel是并发编程的核心,但它们也带来了调试上…

    2026年5月10日
    000
  • 使用 Jupyter Notebook 进行探索性数据分析

    Jupyter Notebook通过单元格实现代码与Markdown结合,支持数据导入(pandas)、清洗(fillna)、探索(matplotlib/seaborn可视化)、统计分析(describe/corr)和特征工程,便于记录与分享分析过程。 Jupyter Notebook 是进行探索性…

    2026年5月10日
    000
  • 《魔兽世界》将于6月11日开启国服回归技术测试

    《魔兽世界》将于6月11日开启国服回归技术测试《魔兽世界》将于6月11日开启国服回归技术测试《魔兽世界》将于6月11日开启国服回归技术测试《魔兽世界》将于6月11日开启国服回归技术测试

    《%ign%ignore_a_1%re_a_1%》官方宣布,将于6月11日开启国服回归技术测试,时间为7天,并称可以在6月内正式开服,玩家们可以访问官网下载战网客户端并预下载“巫妖王之怒”客户端,技术测试详情见下图。 WordAi WordAI是一个AI驱动的内容重写平台 53 查看详情 以上就是《…

    2026年5月10日 用户投稿
    200
  • 网站标题关键词更新后,搜索引擎为何仍显示旧标题?

    网站标题更新后,搜索引擎为何显示旧标题? 网站SEO优化中,站长常修改网站标题关键词,期望搜索结果显示自定义标题。然而,即使更新标签、meta keywords、meta description和结构化数据中的name属性后,搜索结果仍显示旧标题,这令人费解。本文将对此进行解释。 问题:站长修改了网…

    2026年5月10日
    100
  • 深入理解 Express.js 中 next() 参数的作用与中间件机制

    本文深入探讨 express.js 中间件函数中的 `next()` 参数。它负责将控制权传递给请求-响应周期中的下一个中间件或路由处理程序。文章将详细解释 `next()` 的工作原理、中间件的注册与执行顺序,以及不正确使用 `next()` 可能导致请求挂起的风险,并通过代码示例和实际应用场景,…

    2026年5月10日
    000
  • Python命令怎样使用profile分析脚本性能 Python命令性能分析的基础教程

    使用Python的cProfile模块分析脚本性能最直接的方式是通过命令行执行python -m cProfile your_script.py,它会输出每个函数的调用次数、总耗时、累积耗时等关键指标,帮助定位性能瓶颈;为进一步分析,可将结果保存为文件python -m cProfile -o ou…

    2026年5月10日
    000
  • 如何插入查询结果数据_SQL插入Select查询结果方法

    如何插入查询结果数据_SQL插入Select查询结果方法如何插入查询结果数据_SQL插入Select查询结果方法如何插入查询结果数据_SQL插入Select查询结果方法如何插入查询结果数据_SQL插入Select查询结果方法

    使用INSERT INTO…SELECT语句可高效插入数据,通过NOT EXISTS、LEFT JOIN、MERGE语句或唯一约束避免重复;表结构不一致时可通过别名、类型转换、默认值或计算字段处理;结合存储过程可提升可维护性,支持参数化与动态SQL。 将查询结果数据插入到另一个表中,可以…

    2026年5月10日 用户投稿
    000
  • python中zip函数详解 python多序列压缩zip函数应用场景

    zip函数的应用场景包括:1) 同时遍历多个序列,2) 合并多个列表的数据,3) 数据分析和科学计算中的元素运算,4) 处理csv文件,5) 性能优化。zip函数是一个强大的工具,能够简化代码并提高处理多个序列时的效率。 在Python中,zip函数是一个非常有用的工具,它能够将多个可迭代对象打包成…

    2026年5月10日
    000
  • 谷歌浏览器如何截图 谷歌浏览器页面截图技巧

    谷歌浏览器如何截图 谷歌浏览器页面截图技巧谷歌浏览器如何截图 谷歌浏览器页面截图技巧谷歌浏览器如何截图 谷歌浏览器页面截图技巧谷歌浏览器如何截图 谷歌浏览器页面截图技巧

    使用谷歌浏览器的开发者工具截图步骤:1. 按ctrl+shift+i(windows/linux)或cmd+option+i(mac)打开开发者工具。2. 点击右上角三个点,选择”更多工具”,再选择”截图”。3. 选择截取整个页面。推荐的谷歌浏览器扩展…

    2026年5月10日 用户投稿
    100
  • Python中怎样使用pymongo?

    在python中使用pymongo可以轻松地与mongodb数据库进行交互。1)安装pymongo:pip install pymongo。2)连接到mongodb:from pymongo import mongoclient; client = mongoclient(‘mongod…

    2026年5月10日
    000
  • JavaScript函数中插入加载动画(Spinner)的正确方法

    本文旨在解决在JavaScript函数中插入加载动画(Spinner)时遇到的异步问题。通过引入async/await和Promise.all,确保在数据处理完成前后正确显示和隐藏加载动画,提升用户体验。我们将提供两种实现方案,并详细解释其原理和优势。 在Web开发中,当执行耗时操作时,显示加载动画…

    2026年5月10日
    100
  • JS如何实现迭代器?迭代器协议

    JavaScript中实现迭代器需遵循可迭代协议和迭代器协议,通过定义[Symbol.iterator]方法返回具备next()方法的迭代器对象,从而支持for…of和展开运算符;该机制统一了数据结构的遍历接口,实现惰性求值,适用于自定义对象、树、图及无限序列等复杂场景,提升代码通用性与…

    2026年5月10日
    100
  • Golang空接口如何应用在项目中

    空接口可用于接收任意类型值,常见于日志函数、通用数据结构、JSON动态解析及配置驱动逻辑,提升代码灵活性,但需配合类型断言确保安全,避免滥用以降低维护成本。 空接口 interface{} 在 Go 语言中是一个非常灵活的类型,它可以存储任何类型的值。虽然它牺牲了一部分类型安全,但在实际项目中合理使…

    2026年5月10日
    100
  • 三星不再独享,消息称搭载骁龙 8 Gen 3 领先版处理器新机即将发布

    三星不再独享,消息称搭载骁龙 8 Gen 3 领先版处理器新机即将发布三星不再独享,消息称搭载骁龙 8 Gen 3 领先版处理器新机即将发布三星不再独享,消息称搭载骁龙 8 Gen 3 领先版处理器新机即将发布三星不再独享,消息称搭载骁龙 8 Gen 3 领先版处理器新机即将发布

    6 月 15 日消息,据博主@肥威 今日爆料,搭载骁龙 8 Gen 3 领先版%ign%ignore_a_1%re_a_1%的新机即将发布,把之前的 for Galaxy 改成“for Everybody”。 Pic Copilot AI时代的顶级电商设计师,轻松打造爆款产品图片 158 查看详情 …

    2026年5月10日 用户投稿
    100

发表回复

登录后才能评论
关注微信