方法 #1
问题在于必须使用i
,而其余部分必须是随机的,但是要均匀分布。因此,我们可以对其余部分使用np.random.choice
,并将i
添加到末尾,然后进行随机化处理,这就是我们的输出。此外,不需要迭代。
因此,结果如下 -
def create_rand_ar(n,k,i):
sel_ar = np.r_[:i,i+1:n]
sel_ar_incl_i = np.r_[i,np.random.choice(sel_ar, k-1, replace=False)]
np.random.shuffle(sel_ar_incl_i)
return sel_ar_incl_i
为了验证我们始终有
i 在那里,而其余部分具有相等的可能性在输出中,请在大量迭代上运行并检查出现次数的计数,应该是均匀的-
In [84]: n = 7
...: k = 4
...: i = 2
In [85]: outputs = np.array([create_rand_ar(n,k,i) for _ in range(10000)])
In [87]: np.bincount(outputs.ravel())
Out[87]: array([ 5023, 5061, 10000, 4992, 4902, 5006, 5016])
方法二
另一种方法是在[0,1)
范围内创建一个均匀随机数组,将第i个元素设置为某个值< 0
。然后,进行高效的argpartition
并选择前k
个元素,这保证了包括i
且这些元素为最小值。 因此,这就是我们的输出值。
def create_rand_ar_v2(n,k,i):
r = np.random.rand(n)
r[i] = -1
return r.argpartition(k)[:k]
验证分发 -
In [168]: outputs = np.array([create_rand_ar_v2(n,k,i) for _ in range(10000)])
In [169]: np.bincount(outputs.ravel())
Out[169]: array([ 4946, 5055, 10000, 5071, 4972, 5038, 4918])
时间 -
In [165]: n = 7
...: k = 4
...: i = 2
In [166]: %timeit create_rand_ar(n,k,i)
10000 loops, best of 3: 107 µs per loop
In [167]: %timeit create_rand_ar_v2(n,k,i)
100000 loops, best of 3: 2.27 µs per loop
np.random.shuffle
进行修复。 - Yauhen Yakimenkan-1
集生成k-1
子集,然后再添加元素i
有何不同? - Seb