2016-03-14 33 views
1

假設我有N個對象,並且我想將它們劃分成不同大小的M個桶。桶越大,它應該接收的對象越多。將不同大小的M個桶中的N個元素按比例分配到桶大小

我目前已經解決了這個問題,如下所示,但對我來說看起來有點矯枉過正。我現在正在用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) 

最後,我算每個桶ID的出現在樣品中

bucket_id, counts = numpy.unique(sample, return_counts=True) 

我現在可以在內的每個桶中放入元素的數量。

雖然這個工作,我覺得我應該能夠更快地做到這一點,而不生成id列表,然後計算(和排序)。

想法?

EDIT

作爲參考,我已發現對應的但快得多純numpy的溶液。

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

是需求的隨機性部分嗎?或者,例如,如果有100個對象和兩個相同大小的桶,那麼總是會返回一個總是返回[50,50]的方法? –

+0

在你的例子中是的。問題是如何用10個相同大小的桶來管理N = 7。 – marcorossi

回答

1

如果你想有一個隨機分配它不是從問題清晰,「桶大小」建立分配的相對概率一斗。這種隨機分佈被稱爲multinomial distribution。您可以使用numpy.random.multinomial從多項分佈中抽取樣本。例如:

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]) 
+0

隨機確實是我所需要的,在某種程度上什麼是必要的。如何公平地管理N = 2和M = 10? – marcorossi

+1

你仍然可以使用'多項式',它會是「公平的」(至少有一個「公平」的定義)。 10個桶中的每一個都具有被分配兩個對象中的一個的相等機會。當然,這意味着有時兩個對象將被分配到同一個桶。如果這是不可接受的,多項分佈不適合你。 –

+0

這是有效的。我會接受答案! – marcorossi

相關問題