为DataFrame每行识别直接父行并添加父行值至新列
多层级Pandas DataFrame的父行值关联实现
问题描述
现有包含地域层级、行业层级及对应value的Pandas DataFrame,需为每行找到所有直接父行,将父行的value添加为新列(如value-parent-1、value-parent-2,支持更多父行)。由于数据量可能极大,必须兼顾处理速度与内存占用,禁止逐行循环处理。
父行判定逻辑
某行的直接父行需满足:其中一个层级比该行高一级,另一个层级完全一致。例如示例中第5行(地域层级US-California-LA、行业层级All-HT-SoftWare)的直接父行是:
- 地域层级升一级(
US-California),行业层级不变(All-HT-SoftWare) - 行业层级升一级(
All-HT),地域层级不变(US-California-LA)
示例输入数据
| 地域层级 | 行业层级 | value | |
|---|---|---|---|
| 0 | US | All | V1 |
| 1 | US-California | All | V2 |
| 2 | US-California | All-HT | V3 |
| 3 | US-California-LA | All | V4 |
| 4 | US-California-LA | All-HT | V5 |
| 5 | US-California-LA | All-HT-SoftWare | V6 |
| 6 | US-California-LA | All-Manufacturing | V7 |
创建该DataFrame的代码:
import pandas as pd df = pd.DataFrame({ '地域层级': ['US', 'US-California', 'US-California', 'US-California-LA', 'US-California-LA', 'US-California-LA', 'US-California-LA'], '行业层级': ['All', 'All', 'All-HT', 'All', 'All-HT', 'All-HT-SoftWare', 'All-Manufacturing'], 'value': ['V1', 'V2', 'V3', 'V4', 'V5', 'V6', 'V7'] })
预期输出
| 地域层级 | 行业层级 | value | value-parent-1 | value-parent-2 | |
|---|---|---|---|---|---|
| 0 | US | All | V1 | NA | NA |
| 1 | US-California | All | V2 | V1 | NA |
| 2 | US-California | All-HT | V3 | V2 | NA |
| 3 | US-California-LA | All | V4 | V2 | NA |
| 4 | US-California-LA | All-HT | V5 | V3 | V4 |
| 5 | US-California-LA | All-HT-SoftWare | V6 | V5 | NA |
| 6 | US-California-LA | All-Manufacturing | V7 | V4 | NA |
解决方案
步骤1:生成各层级的父级标识
通过字符串分割,为地域、行业层级分别生成对应的父级字符串(去掉最后一个-分隔的子层级):
# 生成地域层级的父级 df['地域父级'] = df['地域层级'].str.rsplit('-', n=1).str[0] # 生成行业层级的父级 df['行业父级'] = df['行业层级'].str.rsplit('-', n=1).str[0]
步骤2:构建父行映射表
将原DataFrame转换为以(地域层级,行业层级)为键、value为值的字典,实现O(1)时间复杂度的快速查找:
hierarchy_map = df.set_index(['地域层级', '行业层级'])['value'].to_dict()
步骤3:批量计算父行value并整理列
通过向量化操作计算两种父行场景的value,再将有效父值整理为动态命名的新列:
# 场景1:地域升一级,行业不变 df['parent_loc'] = df.apply(lambda x: hierarchy_map.get((x['地域父级'], x['行业层级']), pd.NA), axis=1) # 场景2:行业升一级,地域不变 df['parent_ind'] = df.apply(lambda x: hierarchy_map.get((x['地域层级'], x['行业父级']), pd.NA), axis=1) # 过滤空值并整理为父值列表 parent_cols = df[['parent_loc', 'parent_ind']].apply(lambda x: x.dropna().tolist(), axis=1) # 动态生成父列 max_parent_count = parent_cols.str.len().max() for i in range(max_parent_count): df[f'value-parent-{i+1}'] = parent_cols.str.get(i) # 清理中间临时列 df = df.drop(['地域父级', '行业父级', 'parent_loc', 'parent_ind'], axis=1)
方案优势
- 全程采用向量化操作+字典映射,避免逐行循环,处理效率适配大数据量场景
- 自动识别最大父行数量,动态生成对应列,无需预先定义列数
- 使用
pd.NA统一缺失值标识,保持数据一致性
内容的提问来源于stack exchange,提问作者user21143831
相关产品推荐
相关产品推荐

