生成一个numpy.random.choice的2D数组而不进行替换

v440hwme  于 2023-08-05  发布在  其他
关注(0)|答案(2)|浏览(99)

我试图通过删除一些for循环和使用数组来提高代码的速度。现在最慢的一步是生成随机列表。
背景:我在一条染色体上有许多突变,我想随机对1000条长度和突变数目相同但位置随机的“染色体”进行检测。
这是我目前用来产生这些随机突变位置的程式

iterations=1000
Chr_size=1000000
num_mut=500
randbps=[]
for k in range(iterations):
    listed=np.random.choice(range(Chr_size),num_mut,replace=False)
    randbps.append(listed)

字符串
我想执行与this question中所涵盖的内容类似的操作

np.random.choice(range(Chr_size),size=(num_mut,iterations),replace=False)


然而没有替换的情况下,其作为一个整体应用于阵列。
其他上下文:稍后在脚本中,我遍历每个随机化的染色体,并计算给定窗口中的突变数:

for l in range(len(randbps)):

    arr=np.asarray(randbps[l])

    for i in range(chr_last_window[f])[::step]:
    
        counter=((i < arr) & (arr < i+window)).sum()

5tmbdcev

5tmbdcev1#

我不知道np.random.choice是如何实现的,但我猜它是针对一般情况进行优化的。另一方面,你的数字不太可能产生相同的序列。在这种情况下,集合可能更有效,从头开始构建:

import random

def gen_2d(iterations, Chr_size, num_mut):
    randbps = set()
    while len(randbps) < iterations:
        listed = set()
        while len(listed) < num_mut:
            listed.add(random.choice(range(Chr_size)))
        randbps.add(tuple(sorted(listed)))
    return np.array(list(randbps))

字符串
这个函数从一个空集开始,在范围(Chr_size)中生成一个数字,并将该数字添加到集合中。由于集合的属性,它不能再次添加相同的数字。它对randbps也做同样的事情,所以randbps的每个元素也是唯一的。
对于np.random.choice与gen_2d的仅一次迭代:

iterations=1000
Chr_size=1000000
num_mut=500

%timeit np.random.choice(range(Chr_size),num_mut,replace=False)
10 loops, best of 3: 141 ms per loop

%timeit gen_2d(1, Chr_size, num_mut)
1000 loops, best of 3: 647 µs per loop

gv8xihay

gv8xihay2#

基于this solution中使用的技巧,这里有一种方法,它在随机元素数组上使用argsort/argpartition来模拟numpy.random.choice without replacement,以给予randbps作为2D数组-

np.random.rand(iterations,Chr_size).argpartition(num_mut)[:,:num_mut]

字符串
运行时间测试-

In [2]: def original_app(iterations,Chr_size,num_mut):
   ...:     randbps=[]
   ...:     for k in range(iterations):
   ...:         listed=np.random.choice(range(Chr_size),num_mut,replace=False)
   ...:         randbps.append(listed)
   ...:     return randbps
   ...: 

In [3]: # Input params (scaled down version of params listed in question)
   ...: iterations=100
   ...: Chr_size=100000
   ...: num=50
   ...: 

In [4]: %timeit original_app(iterations,Chr_size,num)
1 loops, best of 3: 1.53 s per loop

In [5]: %timeit np.random.rand(iterations,Chr_size).argpartition(num)[:,:num]
1 loops, best of 3: 424 ms per loop

相关问题