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

如何在Pandas DataFrame中按总和占比筛选分组(累计超80%)

问题描述

现有如下Pandas DataFrame数据:

col_a   col_b
a        10
a        20
c        10
c        5
d        20
e        30

其中col_b的总和为95,需求为:按col_a分组后,将各组按组内col_b总和从大到小排序,累加这些组的总和直到超过总总和的80%(即76),保留这些组的所有行,最终需排除col_a为c的行,得到如下结果:

col_a   col_b
a        10
a        20
d        20
e        30

请问如何用Pandas实现该需求?

实现方案

以下是两种简洁的实现方式:

方式一:分步明确处理

import pandas as pd

# 构造原始DataFrame
df = pd.DataFrame({
    'col_a': ['a', 'a', 'c', 'c', 'd', 'e'],
    'col_b': [10, 20, 10, 5, 20, 30]
})

# 1. 计算每组col_b的总和,按总和降序排序
group_sums = df.groupby('col_a')['col_b'].sum().sort_values(ascending=False)

# 2. 计算总总和与阈值
total_sum = df['col_b'].sum()
threshold = total_sum * 0.8

# 3. 计算累加和,筛选目标组
cumulative_sums = group_sums.cumsum()
# 先取累加值未超过阈值的组,再加上首次让累加值超过阈值的组
target_groups = cumulative_sums[cumulative_sums <= threshold].index.tolist()
if len(cumulative_sums) > len(target_groups) and cumulative_sums.iloc[len(target_groups)] > threshold:
    target_groups.append(cumulative_sums.index[len(target_groups)])

# 4. 筛选原始数据中的目标行
result_df = df[df['col_a'].isin(target_groups)]
print(result_df)

方式二:利用移位判断简化代码

import pandas as pd

df = pd.DataFrame({
    'col_a': ['a', 'a', 'c', 'c', 'd', 'e'],
    'col_b': [10, 20, 10, 5, 20, 30]
})

# 分组求和并降序排序
group_sums = df.groupby('col_a')['col_b'].sum().sort_values(ascending=False)
# 计算累加和与阈值
cum_sum = group_sums.cumsum()
threshold = df['col_b'].sum() * 0.8

# 标记需要保留的组:要么累加值未超阈值,要么当前累加值超了但上一个没超(即这个组是导致超过的那个)
keep_mask = cum_sum <= threshold | (cum_sum.shift(1) <= threshold)
target_groups = group_sums[keep_mask].index.tolist()

# 筛选结果
result_df = df[df['col_a'].isin(target_groups)]
print(result_df)

输出结果

两种方式最终都会输出:

col_a  col_b
0     a     10
1     a     20
4     d     20
5     e     30

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.23 01:06:40