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

时间:2014-06-01 15:08:34

标签: 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

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

5 个答案:

答案 0 :(得分:4)

由于您已经在使用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])

由于每个只使用一次,如果你尝试获得比数组大小更多的元素,你会得到一个值错误:

>>> 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'

如果您只想将阵列(或副本)随机播放,也可以使用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])

请注意,将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

这个测试用例 - 速度提高了4倍以上。

答案 1 :(得分:3)

如果您想保持原始列表的顺序相同,并且不想创建shuffle副本,则可以random.sample(lst, n)使用n <= len(lst):< / p>

>>> import random
>>> n = 10
>>> random.sample(xrange(n), n)
[4, 6, 5, 2, 3, 7, 9, 0, 1, 8]

答案 2 :(得分:2)

为什么不随便洗牌并迭代元素:

from random import shuffle

a = list(range(100))

shuffle(a)

>>> print(a)
[5, 82, 96, 66, 47, 62, 49, 86, 55, 4, 21, 94, 34, 46, 10, 32, 83, 13, 25, 24, 58, 74, 14, 43, 18, 42, 56, 23, 52, 36, 15, 60, 79, 29, 0, 72, 38, 88, 41, 85, 57, 69, 30, 45, 70, 31, 84, 63, 92, 48, 68, 22, 40, 59, 95, 11, 39, 78, 89, 64, 6, 20, 91, 37, 61, 28, 71, 12, 8, 19, 1, 98, 50, 97, 26, 53, 73, 17, 16, 87, 33, 9, 99, 90, 93, 81, 7, 44, 65, 80, 54, 51, 67, 27, 3, 2, 76, 77, 75, 35]

答案 3 :(得分:1)

如果您没有任何空间限制,可能会使用np.random.permutation

import numpy as np
rng = np.random.RandomState(42)
redshift=np.array([0.92,0.17,0.51,1.33,0.41,0.82])  # A subset of your array
perm = rng.permutation(len(redshift))
redshift_perm = redshift[perm]

print redshift
print perm
print redshift_perm

# yields
# [ 0.92  0.17  0.51  1.33  0.41  0.82]
# [0 1 5 2 4 3]
# [ 0.92  0.17  0.82  0.51  0.41  1.33]

答案 4 :(得分:0)

您可以使用DOCS中的random.sample:

  

返回从总体中选择的k长度的唯一元素列表   序列。用于无需替换的随机抽样。

示例:

from random import sample
my_list = list(range(10))

for value in sample(my_list,len(my_list)):
    print value