Theres несколько способов сделать это, каждый из них имеет свои плюсы/минусы, следующие четыре, где только из верхней части моей головы ...
- питонов собственного
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
имеет более высокий объем памяти. Я по-прежнему предпочитаю его, так как мне действительно не нужно строить массивы. Мне просто нужен случайный индекс льды ...
$ 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, так что просто придерживаться перетасовать так же быстро.
UPDATE 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 здесь достаточно велик, как таковые вы собираетесь получить повторное число перестановок, перестановками я имею в виду порядок значений не повторяется значений в перестановке, так как принципиально Theres конечного числа перестановок на любом давая конечное множество, если просто вычислить целое множество, то его n !, если только выберем k элементов его n!/(n - k)! и даже если бы это было не так, то есть наш набор был намного больше, мы могли бы получить повторения в зависимости от реализации случайных функций, поскольку shuffle/permutation/... и так далее работают только с текущим набором и не имеют идеи населения, это может быть или не быть приемлемым, зависит от того, чего вы пытаетесь достичь, если вы хотите набор уникальных перестановок, тогда вы собираетесь сгенерировать этот набор и подвыразить его.
Есть ли что-то не так с грязью простой и очевидный случайный импорт; random.shuffle()? –
Интересно, почему это должно быть «numpy»? В общем, numpy для численного типа вычислений, поэтому его имя сокращается для числового python, если оно поддерживает другие типы ... pythons собственный 'random.sample' может быть лучше для этого' [random.sample (['cat' , 'mescaline', 'popcorn'], number_of_members) для индекса в xrange (number_of_arrays)] '... –
@ samy-vilar Причина в том, что я хочу избежать медленных циклов. Я буду использовать это для моделирования в Монте-Карло, поэтому мне понадобятся довольно большие массивы. – Aae