Python 除指定集合中的整数外的整数样本
假设我有一组整数Python 除指定集合中的整数外的整数样本,python,random-sample,Python,Random Sample,假设我有一组整数exceptions=set([3,2,6,…])。使用python从区间[0,n)中随机均匀地抽取整数样本的num最有效的方法是什么 以下是一些我曾经尝试过的想法,但并不令人满意 # Create a set of the integers I am interested in integers = set(range(n)) - exceptions # Draw samples from the set samples = np.random.choice(integers
exceptions=set([3,2,6,…])
。使用python
从区间[0,n)
中随机均匀地抽取整数样本的num
最有效的方法是什么
以下是一些我曾经尝试过的想法,但并不令人满意
# Create a set of the integers I am interested in
integers = set(range(n)) - exceptions
# Draw samples from the set
samples = np.random.choice(integers, num)
在我的例子中,n
相当大(大约10^12),因此创建集合似乎是浪费内存
然而,len(例外)
相对较小(大约10^6),因此拒绝抽样可能是一种合理的方法
samples = []
# Iterate until we have enough samples
while len(samples) < num:
# Draw a sample
proposal = np.random.randint(n)
# Accept or reject
if proposal not in exceptions:
samples.append(proposal)
samples=[]
#迭代直到我们有足够的样本
而len(样本)
不幸的是,所有的循环和集合成员测试都相当慢。显然,我可以编写C
-扩展或使用Cython
,但我想看看你们是否有更好的想法
编辑以在评论中包含建议。我相信,如果异常与n相比很小,那么拒绝可能是你最好的选择;请注意,
n=10**12
和e=10**6
得到无效结果的概率只有百万分之一,因此你不需要拒绝和重新随机选择大多数time。如果你需要多个样本,最好是获取更多的随机数(比如101%),然后批量过滤它们,丢弃异常(我相信numpy中有一种方法可以比循环更快地获取多个样本)。如果仍然有太多样本,只需截断结果;如果太少,生成更多样本
由于异常的规模越来越大,您可以尝试不同的方法:
假设你有一系列的n
整数和e
异常。事实上,你想得到一个n-e
均匀分布的结果。所以有x=np.random.randint(n-e)
应该足够好,只要你能快速将这样的结果转化为有意义的结果。首先,举一个例子来说明这个想法:
- 让我们假设n=100,一组异常={11,12,13,14,15,16,17,18,19,20,26,27}
- 案例1:您的随机结果是60。您必须计算有多少小于或等于60的异常:有13个。因此结果是60+13=73
- 案例2:您的随机结果为22。有10个异常小于该值,因此您将结果增加10,得到32。但是,还有两个异常不大于32,但大于22,因此尚未计算。您必须将该值进一步增加2,最终结果为34
n = ... # full range
exceptions = ... # collection of your exceptions
e = len(exceptions)
def get_sample():
x = np.random.randint(n-e)
skipped = 0
small_exceptions = count_small_exceptions(x, exceptions)
while skipped < small_exceptions:
skipped = small_exceptions
small_exceptions = count_small_exceptions(x+skipped, exceptions)
return x+skipped
n=…#全量程
异常=…#异常的集合
e=len(例外情况)
def get_sample():
x=np.random.randint(n-e)
跳过=0
小异常=计数小异常(x,异常)
跳过
为了实现这一点,您需要一种计算小于给定值的异常的快速方法—模块应该做到这一点,因为它在排序数组上提供了二进制搜索机制
为什么这样做?当skipped==small_exceptions
时循环停止,因此在0..(skipped+x)
范围内确实存在skipped
异常。如果返回值(skipped+x
)如果是异常,循环会更早停止,因为在上一次迭代中会出现更少的异常
准确的成本分析并不是那么容易,但是如果您假设每个
k
常规值都有一个异常,那么后续迭代中的增量每次都要小k倍。最坏的情况是exceptions=range(e)
和randomx
显示为0
。然后将出现e
迭代,每一次迭代都有少量增加。如果e
比n
小,这应该不是问题;否则,您可以通过将异常存储为间隔来进一步改进此解决方案,有效地合并异常所有后续异常仅进入一个“孔”和一个操作。什么类型的异常
?不在异常中的提案
将根据其内容具有不同的性能。例如,列表的成员资格测试为O(N)和O(1)对于集合,平均而言。makeexceptions
集合我编辑了问题,将异常
作为集合
,但主要问题仍然存在。