Pandas DataFrame:基于键列高效映射多列的策略与实践


Pandas DataFrame:基于键列高效映射多列的策略与实践

本教程探讨在pandas dataframe中,如何基于一个“键”列的值,高效地对多个目标列进行条件性映射和数据填充。针对传统方法(如重复使用`numpy.select`)的低效性,文章详细介绍了两种基于向量化操作的优化策略:一是利用`pandas.get_dummies`和`dataframe.mask`构建动态布尔掩码进行条件替换;二是结合`melt`、`merge`和`unstack`进行数据重塑和过滤。通过示例代码和详细解释,帮助读者掌握处理此类数据转换问题的专业技巧。

在数据分析和处理中,我们经常会遇到需要根据DataFrame中某一“键”列的值,有条件地更新或填充其他多个列的场景。例如,如果“键”列的值为'key1',我们可能希望'colA'和'colD'保留其原始值,而其他列则填充为'NA'。当这种映射关系涉及的列数较多时,使用诸如numpy.select或循环迭代的传统方法会变得冗长且效率低下。本教程将深入探讨两种基于Pandas和NumPy的向量化解决方案,以实现高效、简洁的多列条件映射。

首先,我们创建一个示例DataFrame来演示这个问题:

import pandas as pd
import numpy as np

# 创建一个示例DataFrame
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如下:

原始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为'key1'时,保留'colA'和'colD'的值,其他列设为'NA'。
  • 当key为'key2'时,保留'colB'的值,其他列设为'NA'。
  • 当key为'key3'时,保留'colC'的值,其他列设为'NA'。

如果采用逐列使用np.select的方式,代码会非常重复:

# 传统方法(低效且冗余)
# df_copy = df.copy() # 避免修改原始df
# df_copy['colA'] = np.select([df_copy['key'] == 'key1'], [df_copy['colA']], default='NA')
# df_copy['colD'] = np.select([df_copy['key'] == 'key1'], [df_copy['colD']], default='NA')
# df_copy['colB'] = np.select([df_copy['key'] == 'key2'], [df_copy['colB']], default='NA')
# df_copy['colC'] = np.select([df_copy['key'] == 'key3'], [df_copy['colC']], default='NA')
# print("\n使用np.select的结果:")
# print(df_copy)

显然,这种方法在列数和键值组合增多时难以维护。下面我们将介绍两种更专业的向量化解决方案。

方法一:利用 pd.get_dummies 和 DataFrame.where 构建动态掩码

此方法的核心思想是首先构建一个布尔掩码,该掩码能够指示DataFrame中每个单元格是否应该保留其原始值(即是否是有效数据)。然后,使用DataFrame.where()方法根据此掩码进行条件性替换。

  1. 定义键与列的映射关系: 创建一个字典,将每个key值映射到它对应的有效列名列表。

  2. 生成布尔掩码:

    • 将映射字典转换为一个Series,并使用explode()将其展平,使得每个键-列对成为一个独立的条目。
    • 利用pd.get_dummies()将展平的Series转换为一个One-Hot编码的DataFrame,其中列名是所有可能的列,值为布尔类型。
    • 由于explode()会保留原始索引,我们可以使用groupby(level=0).max()来聚合,确保每个原始key对应一行,且该行中所有与该key关联的列都标记为True。
  3. 对齐掩码并应用:

    • 使用mask.reindex(df['key'])将生成的掩码与原始DataFrame的key列对齐,生成一个与原始DataFrame行数相同的布尔DataFrame。
    • 将对齐后的布尔DataFrame转换为NumPy数组,以便与原始DataFrame进行元素级操作。
    • 最后,使用df.where(condition, other)方法,当条件为True时保留原始值,当条件为False时替换为'NA'。
# 重新加载原始DataFrame以确保示例的独立性
df = pd.DataFrame(data)

# 1. 定义键与列的映射关系
key_column_map = {
    'key1': ['colA', 'colD'],
    'key2': ['colB'],
    'key3': ['colC'],
}

# 2. 生成布尔掩码
# 将映射字典转换为Series并展平
s = pd.Series(key_column_map).explode()
# 使用get_dummies创建布尔矩阵,并按原始key聚合
# groupby(level=0).max() 在布尔Series上相当于any(),确保每个key对应的所有True都被保留
mask_template = pd.get_dummies(s, dtype=bool).groupby(level=0).max()

print("\n生成的布尔掩码模板 (mask_template):")
print(mask_template)

# 3. 对齐掩码并应用到DataFrame
# 获取需要处理的列名(排除'key'列)
target_cols = df.columns.difference(['key'])

# 根据df['key']对mask_template进行reindex,使其与df的行对齐
# to_numpy() 转换为NumPy数组以进行高效的元素级操作
aligned_mask = mask_template.reindex(df['key']).to_numpy()

# 使用DataFrame.where()进行条件替换
# df.where(condition, other) - 如果condition为True,保留df的值;否则,使用other的值。
df[target_cols] = df[target_cols].where(aligned_mask, 'NA')

print("\n方法一:使用get_dummies和where的结果:")
print(df)

输出结果:

NoCode NoCode

美团推出的零代码应用生成平台

NoCode 180 查看详情 NoCode
生成的布尔掩码模板 (mask_template):
       colA   colB   colC   colD
key1   True  False  False   True
key2  False   True  False  False
key3  False  False   True  False

方法一:使用get_dummies和where的结果:
    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

优点:

  • 高度向量化,性能优异。
  • 逻辑清晰,通过布尔掩码直观地表达了条件。
  • 适用于大规模数据集。

方法二:通过 melt, merge, 和 unstack 进行数据重塑

此方法利用Pandas的数据重塑能力,将DataFrame转换为“长格式”,然后通过合并操作筛选出有效的数据点,最后再重塑回“宽格式”。

  1. 定义键与列的映射关系: 与方法一相同,使用字典key_column_map。

  2. 重塑原始DataFrame为长格式:

    • 使用reset_index()保留原始行索引,以便后续重塑回宽格式。
    • 使用melt()将除index和key之外的所有列转换为两列:variable(原列名)和value(原单元格值)。
  3. 准备映射关系为DataFrame:

    • 将key_column_map转换为Series并explode(),然后reset_index()将其转换为包含key和variable列的DataFrame。这将作为我们有效键-列对的参照表。
  4. 合并与过滤:

    • 将长格式的DataFrame与步骤3中准备的映射DataFrame进行merge()操作。由于merge()默认只保留匹配的行,这将自动过滤掉所有无效的键-列组合。
  5. 重塑回宽格式并填充:

    • set_index()将index、key和variable设为索引,然后选择value列。
    • unstack('variable', fill_value='NA')将variable列(即原始列名)重新作为新列,并将因merge操作而缺失(即无效)的值填充为'NA'。
    • 最后进行一些索引和列名的清理。
# 重新加载原始DataFrame以确保示例的独立性
df = pd.DataFrame(data)

# 1. 定义键与列的映射关系
key_column_map = {
    'key1': ['colA', 'colD'],
    'key2': ['colB'],
    'key3': ['colC'],
}

# 2. 重塑原始DataFrame为长格式
melted_df = df.reset_index().melt(['index', 'key'])
print("\n中间步骤:melt后的DataFrame:")
print(melted_df.head())

# 3. 准备映射关系为DataFrame
# 将key_column_map转换为DataFrame,用于merge
valid_key_cols = pd.Series(key_column_map).explode().rename_axis('key').reset_index(name='variable')
print("\n中间步骤:有效键-列映射DataFrame:")
print(valid_key_cols)

# 4. 合并与过滤
# 通过merge操作,只保留有效的 (key, variable) 组合
filtered_data = melted_df.merge(valid_key_cols)
print("\n中间步骤:merge过滤后的DataFrame:")
print(filtered_data.head())

# 5. 重塑回宽格式并填充
result_df = (
    filtered_data.set_index(['index', 'key', 'variable'])['value']
    .unstack('variable', fill_value='NA')
    .reset_index('key') # 将'key'从索引移回列
    .rename_axis(index=None, columns=None) # 清理索引和列名
)

# 将结果合并回原始df(如果需要保留原始df的'key'列)
# 或者直接使用result_df,但需要确保所有列都正确对齐
# 这里为了与原始输出格式一致,我们直接构造最终DataFrame
final_df_cols = df.columns.difference(['key'])
df[final_df_cols] = result_df[final_df_cols] # 确保列顺序和名称一致
df['key'] = result_df['key'] # 确保key列也正确

print("\n方法二:使用melt, merge, unstack的结果:")
print(df)

输出结果:

中间步骤:melt后的DataFrame:
   index   key variable    value
0      0  key1     colA  value1A
1      1  key2     colA  value2A
2      2  key3     colA  value3A
3      3  key1     colA  value4A
4      4  key2     colA  value5A

中间步骤:有效键-列映射DataFrame:
    key variable
0  key1     colA
1  key1     colD
2  key2     colB
3  key3     colC

中间步骤:merge过滤后的DataFrame:
   index   key variable    value
0      0  key1     colA  value1A
1      0  key1     colD  value1D
2      1  key2     colB  value2B
3      3  key1     colA  value4A
4      3  key1     colD  value4D

方法二:使用melt, merge, unstack的结果:
    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

优点:

  • 非常灵活,适用于更复杂的数据重塑和过滤场景。
  • 所有操作都是向量化的,效率高。

以上就是Pandas DataFrame:基于键列高效映射多列的策略与实践的详细内容,更多请关注其它相关文章!


# 将其  # 电商大赛推广网站  # 葫芦岛网站推广营销招聘  # 河北区校园营销推广中心  # 贵州网络推广网站大全  # 泰达建设集团网站  # 李勇seo博客最新引流  # 衢州网站建设怎样做  # 同江seo托管  # 汉中关键词排名如何做  # 网站推广是网络营销  # 编码  # 适用于  # 多个  # 创建一个  # 两种  # 递归  # 设为  # 转换为  # 掩码  # 布尔  # red 


相关栏目: 【 Google疑问12 】 【 Facebook疑问10 】 【 优化推广96088 】 【 技术知识133117 】 【 IDC资讯59369 】 【 网络运营7196 】 【 IT资讯61894


相关推荐: CSS绝对定位与溢出控制:实现背景元素局部显示不触发滚动条  毒蘑菇VOLUMESHADER_BM官网首页登录入口 毒蘑菇VOLUMESHADER_BM官网首页登录入口说明  J*aScript模块加载器_RequireJS原理分析  小米civi如何设置锁屏时间  iCloud官方网站 iCloud网页版在线登录入口  百度输入法在AutoCAD中无法输入中文怎么办_百度输入法CAD输入异常解决方法  《环球网校》设置报考省市方法  VBA Outlook邮件自动化:高效集成Excel数据与列标题的策略  Lar*el Eloquent中通过Join查询关联数据表:解决多行子查询问题  Cassandra中复合主键、二级索引与ORDER BY排序的限制与解决方案  word怎么将图片设置为页面背景并不影响打印_Word图片背景设置方法  抖音视频如何添加标题?添加标题有哪些好处?  mysql如何配置从库只读_mysql从库只读设置方法  抖音评论无法发送如何修复 抖音评论功能操作指南  cad怎么隐藏指定的图层_cad隐藏或冻结图层方法  Go反射进阶:访问内嵌结构体中的被遮蔽方法  《下一站江湖2》心法融合技巧  荣耀magicv5怎么上手测评  键盘保修需要什么_键盘售后维修流程  12306夜间购票失败? | 查看官方公布的暂停服务公告与应对方案  Django模型动态关联检查:高效管理复杂关系  Python对象引用与属性赋值:理解链表中的行为  使用document.execCommand实现Web文本编辑器加粗/取消加粗  奥克斯空调不制热啥毛病_奥克斯空调不制热原因分析及解决技巧  sublime如何撤销关闭的标签页_sublime重新打开已关闭文件技巧  《随手记》备份数据方法  深入理解Python对象引用与链表属性赋值  韩剧圈正版官网入口_韩剧圈官方指定登录  原子笔记app误删找回教程  《米姆米姆哈》米姆获取及技能攻略  Python项目中的条件导入:解决跨模块依赖问题  C++如何实现单例模式_C++线程安全的单例模式写法  荣耀盒子应用管理技巧  Chart.js 教程:自定义插件实现图表与图例间距调整  Excel如何制作月度销售统计图_Excel动态图表制作与控件应用  快手网页版官方访问 快手网页版页面在线打开  PHP动态导航按钮:根据用户登录状态切换链接与文本  edge浏览器怎么修改语言为中文_Edge界面语言切换教程  有道AI翻译入口 智能写作官方网站入口  Leaflet地图弹出窗口图片动态显示:避免缺失图标的专业指南  《大周列国志》皇帝律令功能介绍  PHP 4 函数中引用参数的默认值限制与解决方案  mysql如何回滚事务_mysql ROLLBACK事务回滚方法  TikTok笔记文字无法编辑如何解决 TikTok笔记文字编辑优化方法  如何用mysql开发用户注册登录功能_mysql用户注册登录数据库设计  Dash应用中自定义HTML页面标题与网站图标(F*icon)的实用指南  在PHP环境中正确加载HTML资源:CSS样式与图片路径指南  Golang如何使用log记录日志信息_Golang log日志记录方法总结  漫蛙官网(首页入口)_漫蛙漫画稳定访问教程分享  支付宝登录刷脸不是本人如何解决 

 2025-11-27

了解您产品搜索量及市场趋势,制定营销计划

同行竞争及网站分析保障您的广告效果

点击免费数据支持

提交您的需求,1小时内享受我们的专业解答。

运城市盐湖区信雨科技有限公司


运城市盐湖区信雨科技有限公司

运城市盐湖区信雨科技有限公司是一家深耕海外推广领域十年的专业服务商,作为谷歌推广与Facebook广告全球合作伙伴,聚焦外贸企业出海痛点,以数字化营销为核心,提供一站式海外营销解决方案。公司凭借十年行业沉淀与平台官方资源加持,打破传统外贸获客壁垒,助力企业高效开拓全球市场,成为中小企业出海的可靠合作伙伴。

 8156699

 13765294890

 8156699@qq.com

Notice

We and selected third parties use cookies or similar technologies for technical purposes and, with your consent, for other purposes as specified in the cookie policy.
You can consent to the use of such technologies by closing this notice, by interacting with any link or button outside of this notice or by continuing to browse otherwise.