Python 在M个不同尺寸的铲斗中按铲斗尺寸比例划分N个元素

Python 在M个不同尺寸的铲斗中按铲斗尺寸比例划分N个元素,python,numpy,scipy,Python,Numpy,Scipy,假设我有N个对象,我想把它们分成M个大小不同的桶。桶越大,它应该接收的对象越多 我目前已经解决了以下问题,但在我看来,这似乎有些过头了。我现在正在用python/numpy/scipy实现这个问题,这段代码将经常在我的计算密集型科学应用程序中执行 首先,我生成一个离散概率分布: bucket_sizes = numpy.array([10., 7., 3., 20.]) bucket_ratios = bucket_sizes / bucket_sizes.sum() dist = scipy.

假设我有N个对象,我想把它们分成M个大小不同的桶。桶越大,它应该接收的对象越多

我目前已经解决了以下问题,但在我看来,这似乎有些过头了。我现在正在用python/numpy/scipy实现这个问题,这段代码将经常在我的计算密集型科学应用程序中执行

首先,我生成一个离散概率分布:

bucket_sizes = numpy.array([10., 7., 3., 20.])
bucket_ratios = bucket_sizes / bucket_sizes.sum()
dist = scipy.stats.rv_discrete(values=(range(bucket_sizes.size), bucket_ratios))
然后,我生成N个样本:

sample = dist.rcv(size=N)
最后,我统计样本中每个bucket id的出现次数

bucket_id, counts = numpy.unique(sample, return_counts=True)
我现在有了
计数
中每个桶中要放入的元素数

虽然这样做有效,但我觉得我应该能够更快地完成这项工作,而无需生成ID列表,然后进行计数(和排序)

想法

编辑

作为参考,我找到了一个相应但速度更快的纯numpy解决方案

_, counts = numpy.unique(numpy.random.choice(N, bucket_ratios), return_counts=True)

从问题中不清楚您是否想要随机分配,“桶大小”确定了分配到桶的相对概率。这种随机分布称为随机分布。可以使用从多项式分布中提取样本。例如:

In [32]: bucket_sizes
Out[32]: array([10,  7,  3, 20])

In [33]: N
Out[33]: 100

In [34]: p = bucket_sizes / float(bucket_sizes.sum())

In [35]: p
Out[35]: array([ 0.25 ,  0.175,  0.075,  0.5  ])

In [36]: np.random.multinomial(N, p)
Out[36]: array([25, 24,  4, 47])

In [37]: np.random.multinomial(N, p)
Out[37]: array([32, 15,  8, 45])

随机性是需求的一部分吗?或者,例如,如果有100个对象,并且只有两个大小相同的bucket,那么一个总是精确返回[50,50]的方法是否有效?在您的示例中,是的。问题是如何用10个大小相等的桶管理N=7。随机确实是我需要的,在某种程度上是必要的。如何公平地管理N=2和M=10?您仍然可以使用多项式,它将是“公平的”(至少有一个“公平”的定义)。10个桶中的每一个都有均等的机会被指定为两个对象中的一个。当然,这确实意味着有时两个对象将被分配到同一个bucket。如果这是不可接受的,多项式分布将不适用于您。