同行组定义与基于分组实例数阈值的分组平均值计算需求
同行组定义与基于分组实例数阈值的分组平均值计算需求
我完全get到你的需求啦——你希望给每个用户匹配一个「有效参考分组」,优先看Group列,如果这个分组里的样本数≥3,就用它来计算平均值;要是Group不达标,就降级看Sub Group,同样要求样本数≥3;如果两个分组都达不到3个样本的阈值,就标记为NaN,对应的平均值也留空,这样能保证计算出来的平均值足够有意义。下面我就一步步帮你实现这个逻辑:
第一步:还原原始数据集
首先我们先把你给出的原始数据用代码复现出来:
import pandas as pd import numpy as np # 原始数据集 a = pd.DataFrame({ 'Name':['Jack','Peter','Jim','Alex','Dan','Chris'], 'Group':['A','B','C','C','A','A'], 'Sub Group':['a','b','b','c','c','c'], 'Value':[3,5,2,6,7,1] })
第二步:统计各分组的样本量与平均值
我们需要提前计算好每个Group和Sub Group的样本数量,以及对应的Value平均值,这样后面可以快速查询:
# 统计每个Group的样本数和对应Value平均值 group_sample_counts = a['Group'].value_counts().to_dict() group_value_means = a.groupby('Group')['Value'].mean().to_dict() # 统计每个Sub Group的样本数和对应Value平均值 subgroup_sample_counts = a['Sub Group'].value_counts().to_dict() subgroup_value_means = a.groupby('Sub Group')['Value'].mean().to_dict()
第三步:定义逻辑函数生成Label和Average
接下来我们写一个函数,按照你要求的优先级(Group优先,Sub Group次之)来判断每个用户的有效分组,并返回对应的标签和平均值:
def determine_valid_group(row): # 先检查Group是否满足≥3个样本的阈值 if group_sample_counts.get(row['Group'], 0) >= 3: return (row['Group'], group_value_means[row['Group']]) # Group不满足的话,检查Sub Group elif subgroup_sample_counts.get(row['Sub Group'], 0) >= 3: return (row['Sub Group'], subgroup_value_means[row['Sub Group']]) # 两个分组都不满足阈值,返回NaN else: return (np.nan, np.nan)
第四步:应用函数生成目标结果
把函数应用到原始数据的每一行,提取出需要的列,就得到你想要的输出了:
# 把函数结果拆分成Label和Average两列 a[['Label', 'Average']] = a.apply(lambda row: pd.Series(determine_valid_group(row)), axis=1) # 整理成你需要的输出格式 b = a[['Name', 'Label', 'Average']].copy() # 如果你预期输出里Chris的Label是带空格的' A',可以单独调整这一行(如果是笔误的话忽略即可) # b.loc[b['Name'] == 'Chris', 'Label'] = ' A' # 查看最终结果 print(b)
最终结果验证
运行上面的代码后,得到的结果和你的预期完全一致:
| Name | Label | Average |
|---|---|---|
| Jack | A | 3.666667 |
| Peter | NaN | NaN |
| Jim | NaN | NaN |
| Alex | c | 4.666667 |
| Dan | A | 3.666667 |
| Chris | A | 3.666667 |
简单解释下逻辑:
- Jack、Dan、Chris的
Group是A,刚好有3个样本,所以用Group A的平均值 - Alex的
GroupC只有2个样本,不达标,但Sub Groupc有3个样本,所以用Sub Group c的平均值 - Peter的
GroupB只有1个样本,Sub Groupb只有2个样本,都不达标,所以标记为NaN - Jim的情况和Peter一样,也标记为NaN
备注:内容来源于stack exchange,提问作者Derek
相关产品推荐
相关产品推荐

