基于键列高效映射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)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2025年11月28日 22:48:06
下一篇 2025年11月28日 22:48:45

相关推荐

发表回复

登录后才能评论
关注微信