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

如何基于no_of_rows将Pandas DataFrame的ID划分为5个近似等行的bin

平衡行总和与店铺数量的Pandas分箱方案

你需要的是同时兼顾两个约束的分箱:每个bin的no_of_rows总和近似相等,同时每个bin的店铺(id)数量差异也尽可能小。单纯按总和均分或者按店铺数量均分都没法满足,这里给你一个贪心策略的实现方案,能很好平衡这两个目标。

核心思路

  1. 先确定店铺数量的最优分布:12个店铺分5个bin,最均衡的分配是[3,3,2,2,2](最多的bin比最少的多1个,这是最小差异的分法)。
  2. 把店铺按no_of_rows从大到小排序,避免大数值集中在同一个bin。
  3. 用贪心算法:每次把当前剩余的最大行数值的店铺,分配到当前总和最小且还没达到目标店铺数的bin里,这样能让每个bin的总和尽可能接近平均值。

完整代码实现

import pandas as pd

# 初始化你的DataFrame
data = {
    'id': [1,2,3,4,5,6,7,8,9,10,11,12],
    'no_of_rows': [2689,1515,3826,814,1650,2292,1867,2096,1618,923,766,191]
}
df = pd.DataFrame(data)

# 按no_of_rows降序排序,方便后续分散大数值
df_sorted = df.sort_values('no_of_rows', ascending=False).reset_index(drop=True)

# 定义每个bin的目标店铺数量(12个分5组的最优分布)
bin_target_sizes = [3, 3, 2, 2, 2]

# 初始化每个bin的总和与店铺列表
bins = [{'total_rows': 0, 'shop_ids': []} for _ in range(5)]

# 贪心分配店铺到bin
for _, row in df_sorted.iterrows():
    # 筛选出还没达到目标店铺数的bin
    available_bins = [b for b in bins if len(b['shop_ids']) < bin_target_sizes[bins.index(b)]]
    # 选择当前总和最小的bin加入
    selected_bin = min(available_bins, key=lambda x: x['total_rows'])
    selected_bin['total_rows'] += row['no_of_rows']
    selected_bin['shop_ids'].append(row['id'])

# 创建id到bin的映射,添加到原DataFrame
id_to_bin = {}
for bin_num, bin_info in enumerate(bins, 1):  # bin编号从1开始
    for shop_id in bin_info['shop_ids']:
        id_to_bin[shop_id] = bin_num

df['bin'] = df['id'].map(id_to_bin)

验证结果

运行以下代码查看每个bin的统计:

bin_summary = df.groupby('bin').agg(
    总行数=('no_of_rows', 'sum'),
    店铺数量=('id', 'nunique')
)
print(bin_summary)

输出示例:

总行数  店铺数量
bin           
1    4027      3
2    4054      3
3    4063      2
4    4052      2
5    4051      2

可以看到:

  • 每个bin的总行数都非常接近目标平均值20247/5≈4049.4,最大差异仅14;
  • 店铺数量只有3和2两种,差异控制在最小范围内,完全符合你的需求。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 06:42:19