如何以Pythonic方式为Pandas DataFrame按组生成中位数判断标记列?
Pythonic实现DataFrame按组生成中位数判断列
当然有非常Pythonic的实现方式!利用pandas的分组、合并或transform特性,就能轻松完成需求,完全不用写繁琐的循环。下面给你两种简洁的实现方案:
方案一:分组计算中位数 + 合并匹配
这种方式逻辑清晰,容易理解,适合新手快速上手:
import pandas as pd # 初始化原始DataFrame foo = pd.DataFrame( {'var_name': ['r1','r2','r3','var', 'r1','r2','r3','var'], 'group': ['a','a','a','a','b','b','b','b'], 'value': [1,2,3,4,6,7,8,9]} ) # 1. 计算每个组内var_name为r1/r2/r3的value中位数 group_medians = ( foo[foo['var_name'].isin(['r1', 'r2', 'r3'])] # 筛选目标行 .groupby('group')['value'] # 按group分组 .median() # 计算中位数 .rename('group_median') # 重命名列,方便后续合并 ) # 2. 将中位数合并回原DataFrame,让每行都能拿到对应组的中位数 foo = foo.merge(group_medians, on='group', how='left') # 3. 比较value和中位数,生成test列(布尔值转int:True→1,False→0) foo['test'] = (foo['value'] > foo['group_median']).astype(int) # 可选:删除中间辅助列group_median foo = foo.drop('group_median', axis=1) print(foo)
方案二:groupby + apply 紧凑实现
如果想要更紧凑的代码,可以用groupby.apply直接在组内完成计算和判断:
import pandas as pd foo = pd.DataFrame( {'var_name': ['r1','r2','r3','var', 'r1','r2','r3','var'], 'group': ['a','a','a','a','b','b','b','b'], 'value': [1,2,3,4,6,7,8,9]} ) # 定义组内处理函数:计算当前组r1/r2/r3的中位数,再判断每行value是否大于它 def judge_vs_median(group): # 筛选组内目标行,计算中位数 target_median = group.loc[group['var_name'].isin(['r1','r2','r3']), 'value'].median() # 返回每行的判断结果 return group['value'] > target_median # 应用函数到每个组,转成int类型并重置索引 foo['test'] = foo.groupby('group').apply(judge_vs_median).reset_index(drop=True).astype(int) print(foo)
输出验证
两种方案都会得到你预期的结果:
var_name group value test 0 r1 a 1 0 1 r2 a 2 0 2 r3 a 3 1 3 var a 4 1 4 r1 b 6 0 5 r2 b 7 0 6 r3 b 8 1 7 var b 9 1
核心逻辑都是:先按group分组计算指定行的中位数,再将每行的value与对应组的中位数比较,将布尔结果转为0/1,完全符合Pythonic的简洁风格。
内容的提问来源于stack exchange,提问作者quant
相关产品推荐
相关产品推荐

