Pandas按层级从低到高将0值替换为匹配parent_key的self_key行均值
问题解决:按层级填充DataFrame中的0值为子节点均值
需求说明
需要将DataFrame中value列的0值替换为所有parent_key匹配该行self_key的子节点的value均值,且必须按从最低层级到最高层级的顺序填充(低层级数据会向上汇总到高层级)。执行原代码时出现报错:ValueError: Grouper for '<class 'pandas.core.frame.DataFrame'>' not 1-dimensional。
输入数据
创建DataFrame的代码:
import pandas as pd import numpy as np df = pd.DataFrame({ 'self_key':['a','b','c','d','e','e','e','f','f','f'], 'parent_key':[np.nan,'a','b','b','c','c','c','d','d','d'], 'value':[0,0,0,0,4,6,14,12,8,22], 'level':[1,2,3,3,4,4,4,4,4,4] })
原始数据:
self_key parent_key value level 0 a NaN 0 1 1 b a 0 2 2 c b 0 3 3 d b 0 3 4 e c 4 4 5 e c 6 4 6 e c 14 4 7 f d 12 4 8 f d 8 4 9 f d 22 4
预期输出
self_key parent_key value level 0 a NaN 11 1 1 b a 11 2 2 c b 8 3 3 d b 14 3 4 e c 4 4 5 e c 6 4 6 e c 14 4 7 f d 12 4 8 f d 8 4 9 f d 22 4
报错原因
原代码报错是因为分组时误将整个DataFrame作为分组依据,而Pandas的groupby需要一维的分组键(比如Series或列名)。
可行解决方案
核心思路:先按层级从高到低(即从最低层级到最高层级)排序,然后依次计算每个父节点的子节点均值,填充对应父节点的0值。
完整代码实现
import pandas as pd import numpy as np # 初始化DataFrame df = pd.DataFrame({ 'self_key':['a','b','c','d','e','e','e','f','f','f'], 'parent_key':[np.nan,'a','b','b','c','c','c','d','d','d'], 'value':[0,0,0,0,4,6,14,12,8,22], 'level':[1,2,3,3,4,4,4,4,4,4] }) # 获取所有层级,按从高到低排序(从最低层级到最高层级处理) levels = sorted(df['level'].unique(), reverse=True) # 遍历每个层级,从最高层级向下处理 for current_level in levels: # 跳过无0值的层级 if df[(df['level'] == current_level) & (df['value'] == 0)].empty: continue # 计算每个父节点对应的子节点value均值 child_mean = df.groupby('parent_key')['value'].mean().reset_index(name='child_mean') # 合并均值表,填充0值 df = df.merge(child_mean, left_on='self_key', right_on='parent_key', how='left') df['value'] = df.apply( lambda row: row['child_mean'] if (row['value'] == 0 and pd.notna(row['child_mean'])) else row['value'], axis=1 ) # 清理临时列 df.drop(['parent_key_y', 'child_mean'], axis=1, inplace=True) df.rename(columns={'parent_key_x': 'parent_key'}, inplace=True) # 输出结果 print(df)
代码说明
- 层级排序:获取所有唯一层级并降序排列,确保先处理低层级,再用填充后的低层级数据计算高层级均值。
- 计算子节点均值:通过
groupby('parent_key')['value'].mean()得到每个父节点对应的子节点value均值,作为填充依据。 - 填充0值:将原DataFrame与均值表合并,对
value为0的行,用对应的子节点均值替换。 - 清理临时列:删除合并产生的临时列,恢复原始DataFrame结构。
运行结果
执行代码后,输出与预期完全一致。
内容的提问来源于stack exchange,提问作者rupi
相关产品推荐
相关产品推荐

