[英]Taking random samples from a python generator
我for pair in itertools.combinations(bug_map.keys(), 2):
使用函數for pair in itertools.combinations(bug_map.keys(), 2):
來生成我的數據庫中的所有元素對。 問題是元素的數量約為 6.6 K,因此組合數為 21.7 M。此外,組合按字典排序順序發出。
假設我會從生成器中獲取隨機對而不“產生”所有對(只是 n 維的一個子集),我該怎么辦?
如果允許將所有6K
元素作為列表獲取,則首先獲取所有元素,然后使用標准 python 的random.choices()
生成一批帶有替換的樣本。 然后應用排序(因為組合已排序)。 然后刪除兩次或更多內部具有相同元素的元組和相等的元組。 重復批量生成,直到我們得到足夠的n
元組的數量。
您可以將任何k
指定為要在我的代碼中生成的所需元組的長度,並將n
指定為要生成的 k 長度元組的數量。
該算法生成類似於創建k
長度的所有組合然后選擇大小為n
隨機子集的概率分布模式。
import random
#random.seed(0) # Do this only for testing to have reproducible random results
l = list(range(1000, 1000 + 6600)) # Example list of all input elements
k = 2 # Length of each tuple to generate
n = 30 # Number of tuples to generate
batch = max(1, n // 4) # Number of k-tuples to sample at once
maybe_sort = lambda x: sorted(x) if is_sorted else x
res = []
while True:
if len(res) >= n:
res = res[:n]
break
a = random.choices(range(len(l)), k = k * batch) # Generate random samples from inputs with replacement
a = sorted(res + [tuple(sorted(a[i * k + j] for j in range(k))) for i in range(batch)])
res = [a[0]]
for e in a[1:]:
if all(e0 != e1 for e0, e1 in zip(e[:-1], e[1:])) and res[-1] != e:
res.append(e)
print([tuple(l[i] for i in tup) for tup in res])
這可能看起來微不足道,但是如果您想要的樣本數量遠小於可能的組合總數 (21.8 M),那么您可以重復生成ramdom.sample
直到您擁有足夠多的ramdom.sample
。 可能會發生沖突,但(同樣,如果所需的樣本數量相對較少)發生沖突的概率可以忽略不計,不會導致減速。
import random
lst = range(6000)
n = 1000000
k = 2
samples = set()
while len(samples) < n:
samples.add(tuple(random.sample(lst, k)))
即使對於 1,000,000 個隨機樣本,這也僅產生了大約 12k 次碰撞,即大約 1% 的“浪費”迭代,這可能不是什么大問題。
請注意,除了combinations
, ramdom.sample
返回的對沒有排序(第一個元素可以大於第二個),因此您可能需要使用tuple(sorted(...))
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.