You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Pandas分组后按列统计不同阈值以上的数值数量?

Pandas分组后按独立阈值统计达标数量的解决方案

问题背景

需要对数据集按[s_num, ip, f_num, direction]分组,为每个algo_i_score列设置独立阈值,统计每组中超过对应阈值的数值数量,结果中algo_i列对应组内达标个数。

示例数据集

id  s_num   ip  f_num   direction   algo_1_x    algo_2_x    algo_1_score    algo_2_score
0   0.0 0.0 0.0 0.0 X   -4.63   -4.45   0.624356    0.664009
15  19.0    0.0 2.0 0.0 X   -5.44   -5.02   0.411217    0.515843
16  20.0    0.0 2.0 0.0 X   -12.36  -5.09   0.397237    0.541112
20  24.0    0.0 2.0 1.0 X   -4.94   -5.15   0.401744    0.526032
21  25.0    0.0 2.0 1.0 X   -4.78   -4.98   0.386410    0.564934
22  26.0    0.0 2.0 1.0 X   -4.89   -5.03   0.394326    0.513896
24  28.0    0.0 2.0 2.0 X   -4.78   -5.00   0.420078    0.521993
25  29.0    0.0 2.0 2.0 X   -4.91   -5.14   0.407355    0.485878
26  30.0    0.0 2.0 2.0 X   11.83   -4.97   0.392242    0.659122
27  31.0    0.0 2.0 2.0 X   -4.73   -5.07   0.377011    0.524774

尝试代码及报错

尝试的代码:

def count_success(x,thresh):
    return ((x > thresh)*1).sum()

thresholds=[0.1,0.2]
df.groupby(attr_cols).agg({f'algo_{i+1}_score':count_success(thresh) for i, thresh in enumerate(thresholds)})

报错信息:

count_success() missing 1 required positional argument: 'thresh'

疑问:如何为agg()中的自定义函数传递额外参数?或是否有更简便的Pandas内置方法实现需求?


解决方案

方法1:为自定义函数传递额外参数

报错原因是直接调用count_success(thresh)会立即执行函数,而agg需要传入的是函数对象而非执行结果。可以通过以下两种方式传递参数:

方式A:使用functools.partial绑定参数

partial可以固定函数的部分参数,生成一个新的可调用对象,适合agg使用:

from functools import partial
import pandas as pd

def count_success(x, thresh):
    return (x > thresh).sum()  # 布尔值直接求和等价于计数,无需乘1

thresholds = [0.1, 0.2]
# 构建聚合函数字典
agg_funcs = {
    f'algo_{i+1}_score': partial(count_success, thresh=thresh) 
    for i, thresh in enumerate(thresholds)
}

# 分组聚合并调整列名
result = df.groupby(['s_num', 'ip', 'f_num', 'direction']).agg(agg_funcs)
result.columns = [col.replace('_score', '') for col in result.columns]

方式B:使用lambda函数包装

用lambda函数封装原函数和参数,注意要把thresh设为默认参数,避免循环变量引用问题:

import pandas as pd

def count_success(x, thresh):
    return (x > thresh).sum()

thresholds = [0.1, 0.2]
agg_funcs = {
    f'algo_{i+1}_score': lambda x, thresh=thresh: count_success(x, thresh)
    for i, thresh in enumerate(thresholds)
}

result = df.groupby(['s_num', 'ip', 'f_num', 'direction']).agg(agg_funcs)
result.columns = [col.replace('_score', '') for col in result.columns]

方法2:更简便的Pandas内置方法(无需自定义函数)

利用Pandas的广播特性,先对所有score列做阈值判断生成布尔矩阵,再合并分组键后分组求和,代码更简洁高效:

import pandas as pd

thresholds = [0.1, 0.2]
# 提取所有score列并生成阈值判断后的布尔DataFrame
score_cols = [f'algo_{i+1}_score' for i in range(len(thresholds))]
bool_df = df[score_cols] > thresholds

# 合并分组键与布尔结果,分组后求和得到达标数量
result = pd.concat([df[['s_num', 'ip', 'f_num', 'direction']], bool_df], axis=1)\
           .groupby(['s_num', 'ip', 'f_num', 'direction'])\
           .sum()
# 调整列名以符合需求
result.columns = [col.replace('_score', '') for col in result.columns]

内容的提问来源于stack exchange,提问作者Jenny

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.06 07:20:36