无需替换的选择 - 通过改变列表
Selection without replacement - by mutating the list
我正在寻找 Python 中的有效函数,它无需替换即可进行样本选择,但实际上会改变原始列表。也就是说,替代这个:
random.sample(population, k)
在选择样本时从原始列表中删除元素。
列表可能有数百万个项目,并且可能有数十次对示例函数的后续调用。
理想情况下,我想做这样的事情:
sample_size_1 = 5
sample_size_2 = 200
sample_size_3 = 100
population = range(10000000)
sample_1 = select_sample(population, sample_size_1) #population is shrunk
sample_2 = select_sample(population, sample_size_2) #population is shrunk again
sample_3 = select_sample(population, sample_size_3) #and population is shrunk again
其中 population
在每次调用 select_sample 之间有效收缩。
我有一些代码可以在这里展示,但我正在寻找一些已经可用的代码,或者比我的 while 循环更多 "pythonic"。
一个简单的方法是 shuffle your population,这样初始排序是随机的(如果它还不是随机的)。然后从末尾取出元素并删除它们。
您可以通过切片 population[-sample_size:]
获取元素并使用 population[-sample_size:] = []
删除它们。
import random
population = list(range(100))
# Shuffle population so the ordering is random.
random.shuffle(population)
for sample_size in [1, 5, 10]:
sample = population[-sample_size:]
population[-sample_size:] = []
print(sample)
# [79]
# [66, 89, 81, 0, 38]
# [18, 39, 90, 36, 11, 32, 63, 65, 72, 67]
如果您只想一次删除一个元素(即如果 sample_size
为 1),您也可以使用 population.pop()
。
执行此操作的函数将是(假设您的人口已经洗牌):
def select_sample(pop, size):
x = pop[-size:]
pop[-size:] = []
return x
问题是弹出列表中间真的很慢;最后删除是 and certainly fast. As another option, you could use the heap datastructure from heapq
.
中的一种选择
一开始,您会将数据组织到 heapq
中作为元组 (random, value)
;然后使用 heappop
首先弹出随机数最低的值:
import heapq
import random
heap = [ (random.random(), v) for v in samples ]
heapq.heapify(heap)
def select_sample(size):
return [ heapq.heappop(heap)[1] for _ in range(size) ]
在这种情况下,您应该选择弹出列表的末尾,因为这样可以保证更快;但是 heapq
擅长的是在未知大小的总体中选择固定大小的样本。
我正在寻找 Python 中的有效函数,它无需替换即可进行样本选择,但实际上会改变原始列表。也就是说,替代这个:
random.sample(population, k)
在选择样本时从原始列表中删除元素。 列表可能有数百万个项目,并且可能有数十次对示例函数的后续调用。
理想情况下,我想做这样的事情:
sample_size_1 = 5
sample_size_2 = 200
sample_size_3 = 100
population = range(10000000)
sample_1 = select_sample(population, sample_size_1) #population is shrunk
sample_2 = select_sample(population, sample_size_2) #population is shrunk again
sample_3 = select_sample(population, sample_size_3) #and population is shrunk again
其中 population
在每次调用 select_sample 之间有效收缩。
我有一些代码可以在这里展示,但我正在寻找一些已经可用的代码,或者比我的 while 循环更多 "pythonic"。
一个简单的方法是 shuffle your population,这样初始排序是随机的(如果它还不是随机的)。然后从末尾取出元素并删除它们。
您可以通过切片 population[-sample_size:]
获取元素并使用 population[-sample_size:] = []
删除它们。
import random
population = list(range(100))
# Shuffle population so the ordering is random.
random.shuffle(population)
for sample_size in [1, 5, 10]:
sample = population[-sample_size:]
population[-sample_size:] = []
print(sample)
# [79]
# [66, 89, 81, 0, 38]
# [18, 39, 90, 36, 11, 32, 63, 65, 72, 67]
如果您只想一次删除一个元素(即如果 sample_size
为 1),您也可以使用 population.pop()
。
执行此操作的函数将是(假设您的人口已经洗牌):
def select_sample(pop, size):
x = pop[-size:]
pop[-size:] = []
return x
问题是弹出列表中间真的很慢;最后删除是 heapq
.
一开始,您会将数据组织到 heapq
中作为元组 (random, value)
;然后使用 heappop
首先弹出随机数最低的值:
import heapq
import random
heap = [ (random.random(), v) for v in samples ]
heapq.heapify(heap)
def select_sample(size):
return [ heapq.heappop(heap)[1] for _ in range(size) ]
在这种情况下,您应该选择弹出列表的末尾,因为这样可以保证更快;但是 heapq
擅长的是在未知大小的总体中选择固定大小的样本。