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

如何用Pandas将DataFrame按指定大小和数量分箱?含同值归箱需求

解决DataFrame按指定大小/数量分箱,及相同值归为同一箱的需求

没问题,这两个需求都可以轻松实现,我会分步骤给你演示具体操作:

一、基础需求:按固定行数分箱(每箱N条,剩余入最后一箱)

你要的是按排序后的行数均分,每箱固定条数,这种情况直接对索引做分组就能搞定,逻辑非常直观。

针对你提供的小示例(10条数据)

假设我们按D列排序后,每箱3条(对应你给出的预期输出),代码如下:

import pandas as pd
import numpy as np

# 生成示例数据
x = pd.DataFrame(np.random.randint(0,10,size=(10, 4)), columns=list('ABCD'))
# 按D列排序并重置索引
x_sorted = x.sort_values('D').reset_index(drop=True)
# 指定每箱大小
bin_size = 3
# 计算每条数据对应的箱号(箱号从1开始)
x_sorted['bin'] = (x_sorted.index // bin_size) + 1

print(x_sorted)

运行后就能得到和你预期一致的结果:前3条入箱1,中间3条入箱2,最后4条归入箱3。

扩展到10000条数据的场景

如果是你的大DataFrame(10000行),要实现每箱50条、最多100箱的要求,代码逻辑完全通用:

df = pd.DataFrame(np.random.randint(0,10000,size=(10000, 4)), columns=list('ABCD'))
df_sorted = df.sort_values('D').reset_index(drop=True)
bin_size = 50
# 先按固定大小分箱
df_sorted['bin'] = (df_sorted.index // bin_size) + 1
# 限制最多100箱,超出部分全部归入第100箱
df_sorted['bin'] = df_sorted['bin'].clip(upper=100)

这样前99箱各50条,第100箱会收下剩余的10000 - 99*50 = 5050条数据,完全符合你的要求。

二、进阶需求:将相等的值归入同一箱(允许箱大小不均)

这个需求的核心是相同D值不能被拆分到不同箱,哪怕会导致箱大小不一致。这时候不能直接按索引分箱,得先对D值分组,再把连续的同值组合并成箱。

实现思路

  1. 按D值排序后,先统计每个D值的出现次数
  2. 累加这些次数,当累加量接近目标箱大小时就形成一个新箱
  3. 确保同一D值的所有行都被分到同一个箱里

代码实现(以小示例为例)

import pandas as pd
import numpy as np

x = pd.DataFrame(np.random.randint(0,10,size=(10, 4)), columns=list('ABCD'))
x_sorted = x.sort_values('D').reset_index(drop=True)

# 目标参考箱大小(可根据需求调整)
target_bin_size = 3

# 第一步:按D值分组,记录每个D值的起始位置和数量
d_groups = x_sorted.groupby('D').agg(
    start_idx=('D', lambda x: x.index[0]),
    count=('D', 'size')
).reset_index()
d_groups['end_idx'] = d_groups['start_idx'].shift(-1).fillna(len(x_sorted))

# 第二步:遍历分组,合并成箱
current_bin = 1
current_count = 0
bin_assignments = np.zeros(len(x_sorted), dtype=int)

for _, row in d_groups.iterrows():
    start, cnt, end = row['start_idx'], row['count'], row['end_idx']
    # 如果当前箱加上这个D值的数量会超过目标,就新开一个箱
    if current_count + cnt > target_bin_size and current_count != 0:
        current_bin += 1
        current_count = 0
    # 把该D值的所有行分配到当前箱
    bin_assignments[int(start):int(end)] = current_bin
    current_count += cnt

# 把箱号赋值回原DataFrame
x_sorted['bin'] = bin_assignments
print(x_sorted)

这样就能保证所有相同的D值都在同一个箱里,比如示例中的多个1会被全部归入箱1,不会被拆分到其他箱。

大数据量优化方案

如果是10000行的大数据,上面的循环也能跑,但可以用累计求和+分箱的方式提升效率:

df = pd.DataFrame(np.random.randint(0,10000,size=(10000, 4)), columns=list('ABCD'))
df_sorted = df.sort_values('D').reset_index(drop=True)

# 按D值分组,生成每个行对应的组累计计数
df_sorted['d_group'] = df_sorted['D'].astype('category').cat.codes
group_counts = df_sorted.groupby('d_group')['D'].count().cumsum()

# 定义箱的分割点(目标每箱50条)
bin_cutoffs = np.arange(50, group_counts.iloc[-1], 50)
# 用累计计数分箱,确保同D值在同一箱
df_sorted['bin'] = pd.cut(
    group_counts.reindex(df_sorted.index),
    bins=[0] + bin_cutoffs.tolist() + [np.inf],
    labels=np.arange(1, len(bin_cutoffs)+2)
).astype(int)

这个方法效率更高,适合处理大规模数据集,同时依然能保证相同D值不被拆分。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 03:31:38