如何将DataFrame子组的最低Rank值赋值给对应父层级?
解决层级DataFrame中子集最差状态赋值给父层级的问题
首先得明确你的核心需求:给那些标记为contains_subsets=1.0的父层级行,赋值它所有子节点里的最差状态(也就是最小的Rank_Numeric值,以及对应的文本状态rank)。你之前的尝试没生效,是因为条件判断的逻辑偏差了,咱们一步步来修正实现。
问题分析:为啥之前的代码没效果?
你用df1.loc[df1['hierarchy'] == df1['parent'], ...]这个条件是不对的——父节点的hierarchy是它自身的层级(比如2.11.3),而它的parent是上一层级(2.11),两者永远不会相等。正确的逻辑应该是:子节点的parent等于父节点的hierarchy,所以我们需要先按子节点的parent分组计算最小值,再匹配回对应的父节点行。
完整实现步骤
1. 准备反向映射字典(数值转状态文本)
因为我们之后需要把计算出的最小数值Rank转回对应的文本状态,先定义反向字典:
reverse_dict = {v: k for k, v in dictionary.items()}
2. 计算每个父节点对应的子节点最小Rank
先筛选出所有子节点(contains_subsets为NaN的行),然后按parent分组,计算每组的最小Rank_Numeric:
# 按子节点的parent分组,计算每组的最小Rank数值 parent_min_rank = df1[df1['contains_subsets'].isna()].groupby('parent')['Rank_Numeric'].min().reset_index() # 重命名列,方便后续和原DataFrame合并 parent_min_rank.columns = ['hierarchy', 'min_rank']
这一步得到的parent_min_rank里,hierarchy就是父节点的层级字符串,min_rank是该父节点所有子节点的最差Rank数值。
3. 合并结果并更新父节点
把计算出的最小值合并回原DataFrame,然后更新父节点的Rank_Numeric和rank列:
# 合并原DataFrame和最小rank数据 df1 = df1.merge(parent_min_rank, on='hierarchy', how='left') # 仅更新contains_subsets=1.0的父节点行 df1.loc[df1['contains_subsets'] == 1.0, 'Rank_Numeric'] = df1['min_rank'] df1.loc[df1['contains_subsets'] == 1.0, 'rank'] = df1['min_rank'].map(reverse_dict) # 可选:删除临时的min_rank列 df1 = df1.drop('min_rank', axis=1)
完整可运行代码
把所有步骤整合起来,直接运行就能得到你想要的结果:
import pandas as pd # 初始化你的原始DataFrame data = [ [1.0, '1.1', None, None], [1.0, '2.11.3', None, None], [None, '2.11.3.1', 'Good', None], [None, '2.11.3.10', 'Warning', None], [None, '2.11.3.11', 'Warning', None], [None, '2.11.3.12', 'Good', None], [1.0, '2.11.3.13', None, None], [None, '2.11.3.13.1', 'Critical', None], [None, '2.11.3.13.2', 'Critical', None], [None, '2.11.3.13.3', 'Good', None], [None, '2.11.3.13.4', 'Good', None], [None, '2.11.3.13.5', 'Good', None], [1.0, '2.11.3.14', None, None], [None, '2.11.3.14.1', 'Warning', None], [None, '2.11.3.14.11', 'Critical', None], [None, '2.11.3.14.12', 'Warning', None], [None, '2.11.3.14.13', 'Good', None], [None, '2.11.3.14.14', 'Good', None] ] df1 = pd.DataFrame(data, columns=['contains_subsets', 'hierarchy', 'rank', 'Rank_Numeric']) # 转换rank为数值 dictionary = {'Good':3, 'Warning':2, 'Critical':1} df1['Rank_Numeric'] = df1['rank'].map(dictionary) # 生成parent列 df1['parent'] = df1['hierarchy'].apply(lambda x: '.'.join(x.split('.')[:-1])) # 反向字典:数值转文本状态 reverse_dict = {v: k for k, v in dictionary.items()} # 计算每个父节点的子节点最小Rank parent_min_rank = df1[df1['contains_subsets'].isna()].groupby('parent')['Rank_Numeric'].min().reset_index() parent_min_rank.columns = ['hierarchy', 'min_rank'] # 合并并更新父节点 df1 = df1.merge(parent_min_rank, on='hierarchy', how='left') df1.loc[df1['contains_subsets'] == 1.0, 'Rank_Numeric'] = df1['min_rank'] df1.loc[df1['contains_subsets'] == 1.0, 'rank'] = df1['min_rank'].map(reverse_dict) df1 = df1.drop('min_rank', axis=1) print(df1)
运行后就能得到你预期的结果:父节点的rank和Rank_Numeric会被正确更新为其子节点的最差状态。
内容的提问来源于stack exchange,提问作者robert_553z8
相关产品推荐
相关产品推荐

