只随机选择列表中的所有元素一次

Dal*_*lek 1 python numpy matplotlib scipy

如何从包含n元素的列表中随机选择一个数字,n而不选择列表中的相同元素两次。我写了一个代码来选择列表中元素的序列号,但是速度很慢:

>>>redshift=np.array([0.92,0.17,0.51,1.33,....,0.41,0.82])
>>>redshift.shape
(1225,)
exclude=[]
k=0
ng=1225
while (k < ng):
      flag1=0
      sq=random.randint(0, ng)
      while (flag1<1):
        if sq in exclude:
           flag1=1
           sq=random.randint(0, ng)
        else:
           print sq
           exclude.append(sq)
           flag1=0
      z=redshift[sq]
      k+=1
Run Code Online (Sandbox Code Playgroud)

它不会选择列表中元素的所有序列号。

daw*_*awg 6

由于您已经在使用 numpy 数组,您不妨使用该包中的工具。

您可以将numpy.random.choicereplace=False. 那只会使用每个元素一次:

>>> redshift=np.array([0.92,0.17,0.51,1.33,0.41,0.82])
>>> np.random.choice(redshift, redshift.size, replace=False)
array([ 0.41,  0.82,  0.17,  1.33,  0.92,  0.51])
Run Code Online (Sandbox Code Playgroud)

由于每个只使用一次,如果您尝试获取超过数组大小的元素,则会出现值错误:

>>> np.random.choice(redshift, redshift.size+1, replace=False)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "mtrand.pyx", line 1051, in mtrand.RandomState.choice (numpy/random/mtrand/mtrand.c:8075)
ValueError: Cannot take a larger sample than population when 'replace=False'
Run Code Online (Sandbox Code Playgroud)

如果您只想将数组(或副本)原地打乱,您也可以使用np.random.shuffle

>>> redshift
array([ 0.92,  0.17,  0.51,  1.33,  0.41,  0.82])
>>> np.random.shuffle(redshift)
>>> redshift
array([ 0.41,  0.82,  1.33,  0.51,  0.92,  0.17])
Run Code Online (Sandbox Code Playgroud)

请注意,将 numpy 数组保存在 numpy 中比切换回 Python 数据结构来执行诸如获取排序版本之类的操作要快得多:

>>> from timeit import timeit
>>> import random
>>> source=range(1000000)
>>> a=np.array(source)
>>> timeit('np.random.choice(a, a.size, replace=False)', setup='from __main__ import np, a', number=10)
2.971310766064562
>>> timeit('random.sample(list(a), a.size)', setup='from __main__ import random, a', number=10)
14.129850425058976
Run Code Online (Sandbox Code Playgroud)

在这个测试用例中——快了 4 倍以上。