如何用Pandas groupby transform获取分组后Rank大于0的最小值?
问题描述
现有如下结构的Pandas DataFrame:
Race_ID Date Student_ID Rank 1 1/1/2023 1 3 1 1/1/2023 2 8 1 1/1/2023 3 0 1 1/1/2023 4 4 2 11/9/2022 1 2 2 11/9/2022 2 3 2 11/9/2022 3 9 3 17/4/2022 5 0 3 17/4/2022 2 1 3 17/4/2022 3 2 3 17/4/2022 4 5 4 1/3/2022 1 6 4 1/3/2022 2 2 5 1/1/2021 1 0 5 1/1/2021 2 3 5 1/1/2021 3 1
需要新增一列min>0,该列的值为按Race_ID分组后,Rank字段中大于0的最小值,预期结果如下:
Race_ID Date Student_ID Rank min>0 1 1/1/2023 1 3 3 1 1/1/2023 2 8 3 1 1/1/2023 3 0 3 1 1/1/2023 4 4 3 2 11/9/2022 1 2 2 2 11/9/2022 2 3 2 2 11/9/2022 3 9 2 3 17/4/2022 5 0 1 3 17/4/2022 2 1 1 3 17/4/2022 3 2 1 3 17/4/2022 4 5 1 4 1/3/2022 1 6 2 4 1/3/2022 2 2 2 5 1/1/2021 1 0 1 5 1/1/2021 2 3 1 5 1/1/2021 3 1 1
已知groupby和transform('min')的用法,但不清楚如何添加“Rank大于0”的筛选条件。
解决方案
提供几种实用的实现方式:
方法1:groupby+apply自定义筛选逻辑
通过apply对每个分组的Rank列筛选出大于0的值,再取最小值:
df['min>0'] = df.groupby('Race_ID')['Rank'].apply(lambda x: x[x > 0].min())
方法2:替换0为NaN后使用transform('min')
利用min()计算自动忽略NaN的特性,先将Rank中的0替换为NaN,再分组取最小值:
df['min>0'] = df['Rank'].mask(df['Rank'] == 0).groupby(df['Race_ID']).transform('min')
也可以用replace实现替换:
df['min>0'] = df['Rank'].replace(0, float('nan')).groupby(df['Race_ID']).transform('min')
方法3:groupby+transform结合自定义函数
把筛选和取最小值的逻辑封装成函数,传给transform:
def min_positive(x): return x[x > 0].min() df['min>0'] = df.groupby('Race_ID')['Rank'].transform(min_positive)
以上方法都能得到预期结果,其中方法2的性能更优,适合处理大数据量场景。
内容的提问来源于stack exchange,提问作者Ishigami
相关产品推荐
相关产品推荐

