模拟 random.sample() 进行非均匀分布



我想在python中模拟random.sample((的功能,但选择分布不均匀(在这种情况下为三角形(。重要的是,单个项目不会被选择两次(如 random.sample 文档中所述(。这是我所拥有的:

...
def tri_sample(population, k, mode=0):
"""
Mimics the functionality of random.sample() but with a triangular
distribution over the length of the sequence.
Mode defaults to 0, which favors lower indices.
"""
psize = len(population)
if k > psize:
raise ValueError("k must be less than the number of items in population.")
if mode > psize:
raise ValueError("mode must be less than the number of items in population.")
indices_chosen = []
sample = []
for i in range(k):
# This ensures unique selections
while True:
choice = math.floor(random.triangular(0, psize, mode))
if choice not in indices_chosen:
break
indices_chosen.append(choice)
sample.append(population[choice])
return sample
...

我怀疑这不是防止拉取重复项目的理想方法。我在设计这个时的第一个想法是复制population并在采样时.pop()项目,以防止两次选择相同的项目,但我看到了两个问题:

  1. 如果population是对象列表,则复制列表时可能会有一些困难,同时仍确保sample中的项指向population中的相同对象。
  2. 对人口使用.pop()会改变人口的规模,每次都会改变分布。理想情况下,无论选择项目的顺序如何,分布(不确定我是否正确使用了该术语 - 调用每个项目的概率(都是相同的。

有没有更有效的方法从总体中获取非均匀随机样本?

你可以通过使用numpy.random.choice来实现你想要的

此函数的输入如下所示:

numpy.random.choice(a, size=None, replace=True, p=None)

因此,您可以将权重向量p指定为所需的概率分布,并选择replace=False,这样样本就不会重复。

或者,您可以使用numpy.random.triangular直接从三角分布中采样。您可以在循环中执行此操作,并且仅当新结果以前未出现时才将其添加到列表中。

最新更新