我使用random.sample
从一个非常大的范围内采样,这取决于输入负载。有时样本本身非常大,由于它是一个列表,它占用了大量内存。
应用程序不一定使用列表中的所有值。如果random.sample
可以返回一个列表生成器而不是列表本身,那就太好了。
现在我有一个包装器,它将大的输入范围分成大小相等的桶,并使用randint
从每个n / sample_size
桶中选择一个随机数。
编辑:在我的情况下,输入是连续的,我有这个包装函数来模拟随机。示例作为生成器,但这并不能真正复制功能,因为它在最后跳过了一些元素。
import random
def samplegen( start, end, sample_size ):
bktlen = ( end - start ) / sample_size
for i in xrange( sample_size ): #this skips the last modulo elements
st = start + (i * bktlen)
yield random.randrange( st, st + bktlen )
既然您评论说顺序无关紧要(我已经问过它是否必须是随机的还是可以排序),这可能是一个选项:
import random
def sample(n, k):
"""Generate random sorted k-sample of range(n)."""
for i in range(n):
if random.randrange(n - i) < k:
yield i
k -= 1
遍历这些数字,并以概率
包括样本中的每个数字numberOfNumbersStillNeeded/numberOfNumbersStillLeft
>>> for _ in range(5):
print(list(sample(100, 10)))
[7, 16, 41, 50, 55, 56, 61, 76, 89, 96]
[5, 13, 24, 28, 34, 35, 40, 64, 80, 95]
[9, 18, 19, 36, 38, 39, 61, 73, 84, 85]
[23, 24, 26, 28, 40, 53, 62, 76, 77, 91]
[2, 12, 21, 41, 60, 68, 70, 72, 90, 91]
为什么不像下面这样——set seen
只增长到k
的函数,而不一定增长到population
的大小:
import random
def sample(population, k):
seen = set()
for _ in range(k):
element = random.randrange(population)
while element in seen:
element = random.randrange(population)
yield element
seen.add(element)
for n in sample(1000000, 10):
print(n)
另一种方法可能是使用原始桶设计,但使用索引本身随机抽样的非均匀桶:
import random
def samplegen(start, end, sample_size):
random_bucket_indices = random.sample(range(start, end), sample_size)
sorted_bucket_indices = sorted(random_bucket_indices) + [end + 1]
for index in random_bucket_indices:
yield random.randrange(index, sorted_bucket_indices[sorted_bucket_indices.index(index) + 1])