在使用pandas处理表格数据时,经常会遇到子行的部分字段为空,需要参考父行对应键的数值进行回填的场景,比如组织架构表中下属部门的部分属性缺失,需要沿用上级部门的对应属性值。

核心实现思路
实现父行对应键值回填空值的核心逻辑可以分为三步:
- 首先给数据添加标识父行的关联键,比如通过层级ID、父ID等字段确定父子关系
- 然后通过关联键匹配到当前空值行对应的父行数据
- 最后将父行对应字段的值回填到子行的空值位置
完整代码示例
下面构造一个模拟的组织架构数据,其中子部门的属性字段存在空值,需要回填上级部门的对应值:
import pandas as pd
import numpy as np
# 构造测试数据,dept_id是部门ID,parent_id是上级部门ID,attr1是需要回填的属性
data = {
'dept_id': [1, 2, 3, 4, 5],
'parent_id': [np.nan, 1, 1, 2, 2],
'dept_name': ['总部', '技术部', '产品部', '前端组', '后端组'],
'attr1': ['A类', np.nan, np.nan, np.nan, np.nan]
}
df = pd.DataFrame(data)
print("原始数据:")
print(df)
# 步骤1:通过parent_id关联父行数据,获取父行的attr1值
# 将父行的dept_id和attr1提取出来作为映射表
parent_map = df[['dept_id', 'attr1']].dropna(subset=['attr1']).set_index('dept_id')['attr1'].to_dict()
# 步骤2:定义填充函数,根据parent_id从映射表获取父行值填充空值
def fill_with_parent(row):
if pd.isna(row['attr1']) and not pd.isna(row['parent_id']):
return parent_map.get(row['parent_id'], np.nan)
return row['attr1']
# 步骤3:应用填充函数
df['attr1'] = df.apply(fill_with_parent, axis=1)
print("n填充后数据:")
print(df)
代码逻辑说明
上述代码首先构造了包含父子关系的测试DataFrame,其中子部门的attr1字段为np.nan空值。接着通过parent_map建立部门ID到父行属性值的映射关系,只保留父行中attr1非空的数据。然后定义fill_with_parent函数,判断当前行的attr1是否为空且存在父ID,如果是则从映射表中获取父行的attr1值,否则保留原值。最后通过apply方法对每一行应用填充逻辑,完成空值回填。
复杂场景适配
如果存在多级父子关系,比如需要向上递归查找最近的父行非空值,可以调整填充逻辑:
def fill_recursive(row, df, depth=0):
# 递归深度限制,避免无限循环
if depth > 10:
return np.nan
if not pd.isna(row['attr1']):
return row['attr1']
if pd.isna(row['parent_id']):
return np.nan
# 查找父行
parent_row = df[df['dept_id'] == row['parent_id']]
if parent_row.empty:
return np.nan
# 递归获取父行的attr1值
return fill_recursive(parent_row.iloc[0], df, depth + 1)
df['attr1'] = df.apply(lambda x: fill_recursive(x, df), axis=1)
print("n递归填充后数据:")
print(df)
该递归方法会不断向上查找父行的attr1值,直到找到非空值或者达到递归深度限制,适用于多级嵌套的父子结构数据。