如何在Pandas中按b列等和对a列进行n个区间分箱?
按b列总和均衡划分a列区间的解决方案
你需要把DataFrame的a列分成n个区间,同时让每个区间对应的b列总和尽量相等,而不是用pd.cut默认方式导致的b总和差异悬殊。下面是具体实现步骤:
实现步骤
1. 先对a列排序
因为要基于a的顺序累计b的值,所以先做排序处理:
df_sorted = df.sort_values('a').reset_index(drop=True)
2. 计算b的累计和并确定分组边界
核心逻辑是通过b的累计和分位数来定位a的区间边界,确保每个分组的b总和接近:
# 计算b列的累计和 df_sorted['b_cumsum'] = df_sorted['b'].cumsum() # 计算b列的总数值,用来推导每个分组的累计阈值 total_b = df_sorted['b_cumsum'].iloc[-1] # 假设分成5组,生成4个中间阈值(组数n对应n-1个中间阈值) n_groups = 5 group_thresholds = [i * total_b / n_groups for i in range(1, n_groups)] # 找出对应阈值的a值作为区间边界 bin_edges = [df_sorted['a'].iloc[0]] # 区间起始值 for threshold in group_thresholds: # 找到第一个累计和超过阈值的行,取对应的a值作为边界 idx = df_sorted[df_sorted['b_cumsum'] >= threshold].index[0] bin_edges.append(df_sorted['a'].iloc[idx]) bin_edges.append(df_sorted['a'].iloc[-1]) # 区间结束值
3. 用pd.cut生成分组结果
将上面得到的边界传入pd.cut,给原始DataFrame添加分组列:
df['a_group'] = pd.cut(df['a'], bins=bin_edges, include_lowest=True)
4. 验证分组效果
查看每个分组的b总和,确认是否均衡:
print(df.groupby('a_group')['b'].sum())
关键说明
- 这种方法本质是按b的累计贡献划分a的区间,和
pd.cut默认按a的数值/频数分组逻辑不同,能保证每个分组的b总和尽可能接近。 - 要调整分组数量,只需要修改代码中的
n_groups值即可。
内容的提问来源于stack exchange,提问作者chikich
相关产品推荐
相关产品推荐

