Python中有my_sample = random.sample(range(100), 10)
以从[0,100)
的范围内无重复随机采样。
假设我已经随机采样了n
个数,现在我想要再采样一个数而不重复(不包括之前采样的n
个数),如何高效地实现?
更新:从“相对高效”更改为“超级高效”(但忽略常数因子)
Python中有my_sample = random.sample(range(100), 10)
以从[0,100)
的范围内无重复随机采样。
假设我已经随机采样了n
个数,现在我想要再采样一个数而不重复(不包括之前采样的n
个数),如何高效地实现?
更新:从“相对高效”更改为“超级高效”(但忽略常数因子)
一行简洁的代码(O(n + m)
,其中 n 代表范围,m 代表旧样本量):
next_sample = random.sample(set(range(100)).difference(my_sample), 10)
O(n)
的,所以即使对于1000万个元素,它也只需要不到一秒钟的时间。 - Chronialdef sample_n_points_without_replacement(n, set_of_points):
sampled_point_indices = random.sample(range(len(set_of_points)), n)
sampled_point_indices.sort(reverse=True)
sampled_points = [set_of_points[sampled_point_index] for sampled_point_index in sampled_point_indices]
for sampled_point_index in sampled_point_indices:
del(set_of_points[sampled_point_index])
return sampled_points, set_of_points
sample_space
)上进行无替换抽样的完全相同问题,但是您不是在尚未抽样的元素集合上均匀抽样,而是给定了一个初始概率分布p
,告诉您在整个空间中抽样时抽取第i^th
个元素的概率。
然后,使用numpy的以下实现是数值稳定的:
import numpy as np
def iterative_sampler(sample_space, p=None):
"""
Samples elements from a sample space (a list)
with a given probability distribution p (numPy array)
without replacement. If called until StopIteration is raised,
effectively produces a permutation of the sample space.
"""
if p is None:
p = np.array([1/len(sample_space) for _ in sample_space])
try:
assert isinstance(sample_space, list)
assert isinstance(p, np.ndarray)
except AssertionError:
raise TypeError("Required types: \nsample_space: list \np type: np.ndarray")
# Main loop
n = len(sample_space)
idxs_left = list(range(n))
for i in range(n):
idx = np.random.choice(
range(n-i),
p= p[idxs_left] / p[idxs_left].sum()
)
yield sample_space[idxs_left[idx]]
del idxs_left[idx]
这篇文章简短而精炼,我很喜欢。请告诉我你们的想法!
[0, x)
范围内采样整数?你期望的x
是多少? - Chronialrandom.sample
的源代码。 - Eric