即使世界幾個這樣的方式,每個人都有自己的優點/缺點,以下四個地方只是 從我的頭頂......
- 蟒蛇自己
random.sample
,雖然它可能不是最快...
numpy.random.permutation
再簡單但它創建了我們必須切片的副本,ouch!
numpy.random.shuffle
因爲它洗牌到位,速度更快,但我們仍需要切片。
numpy.random.sample
是最快的,但它只能在區間0到1,所以我們必須 正常化它,並將其轉換爲整數來獲得隨機指數,在最後我們還是 要切片,注正火到我們想要的大小不會產生均勻的隨機分佈。
這是一些基準。
import timeit
from matplotlib import pyplot as plt
setup = \
"""
import numpy
import random
number_of_members = 20
values = range(50)
"""
number_of_repetitions = 20
array_sizes = (10, 200)
python_random_times = [timeit.timeit(stmt = "[random.sample(values, number_of_members) for index in xrange({0})]".format(array_size),
setup = setup,
number = number_of_repetitions)
for array_size in xrange(*array_sizes)]
numpy_permutation_times = [timeit.timeit(stmt = "[numpy.random.permutation(values)[:number_of_members] for index in xrange({0})]".format(array_size),
setup = setup,
number = number_of_repetitions)
for array_size in xrange(*array_sizes)]
numpy_shuffle_times = [timeit.timeit(stmt = \
"""
random_arrays = []
for index in xrange({0}):
numpy.random.shuffle(values)
random_arrays.append(values[:number_of_members])
""".format(array_size),
setup = setup,
number = number_of_repetitions)
for array_size in xrange(*array_sizes)]
numpy_sample_times = [timeit.timeit(stmt = \
"""
values = numpy.asarray(values)
random_arrays = [values[indices][:number_of_members]
for indices in (numpy.random.sample(({0}, len(values))) * len(values)).astype(int)]
""".format(array_size),
setup = setup,
number = number_of_repetitions)
for array_size in xrange(*array_sizes)]
line_0 = plt.plot(xrange(*array_sizes),
python_random_times,
color = 'black',
label = 'random.sample')
line_1 = plt.plot(xrange(*array_sizes),
numpy_permutation_times,
color = 'red',
label = 'numpy.random.permutations'
)
line_2 = plt.plot(xrange(*array_sizes),
numpy_shuffle_times,
color = 'yellow',
label = 'numpy.shuffle')
line_3 = plt.plot(xrange(*array_sizes),
numpy_sample_times,
color = 'green',
label = 'numpy.random.sample')
plt.xlabel('Number of Arrays')
plt.ylabel('Time in (s) for %i rep' % number_of_repetitions)
plt.title('Different ways to sample.')
plt.legend()
plt.show()
和結果:
所以看起來numpy.random.permutation
是最差的,並不奇怪,蟒蛇自己random.sample
拿着它自己的,所以它看起來像numpy.random.shuffle
之間的緊密的賽程和numpy.random.sample
與numpy.random.sample
衝出來,所以要麼應該足夠,即使numpy.random.sample
有更高的內存佔用我仍然喜歡它,因爲我真的不需要構建陣列我只需要隨機ind冰...
$ uname -a
Darwin Kernel Version 10.8.0: Tue Jun 7 16:33:36 PDT 2011; root:xnu-1504.15.3~1/RELEASE_I386 i386
$ python --version
Python 2.6.1
$ python -c "import numpy; print numpy.__version__"
1.6.1
UPDATE
可惜numpy.random.sample
不借鑑人口獨特的元素,所以你會得到repitation,所以才堅持洗牌一樣快。
更新2
如果你想保持numpy的範圍內充分利用它的一些內置的功能,就像這些值轉換爲numpy的陣列。
import numpy as np
values = ['cat', 'popcorn', 'mescaline']
number_of_members = 2
N = 1000000
random_arrays = np.asarray([values] * N)
_ = [np.random.shuffle(array) for array in random_arrays]
subset = random_arrays[:, :number_of_members]
注意到,N這裏是因爲這樣你會得到置換的重複次數,由排列我的意思是值的順序排列內不重複的值,因爲從根本上那裏有任何置換的有限數量相當大給出有限集合,如果只計算整個集合然後它的n !,如果只選擇k個元素它的n!/(n - k)!即使情況並非如此,這意味着我們的集合要大得多,但是依賴於隨機函數實現,我們仍然可能會重複,因爲shuffle/permutation/...等僅適用於當前集合,並且不知道的人口,這可能或可能不可接受,取決於你想要達到的目標,如果你想要一組獨特的排列,那麼你將生成該集合並對其進行二次抽樣。
污垢是否有毛病簡單明顯進口隨機; random.shuffle()? –
我不知道爲什麼它必須是'numpy'?一般numpy是用於數值類型的計算,因此它的名字是數字python的縮寫,並且它支持其他類型...... pythons擁有'random.sample'可能更適合這個'[random.sample(['cat' ,'mescaline','爆米花'],number_of_members)的索引在xrange(number_of_arrays)]'... –
@ samy-vilar原因是我想避免慢循環。我將用它來進行蒙特卡洛模擬,所以我需要相當大的數組。 – Aae