Неповторяющееся случайное число в numpy

88

Как я могу генерировать неповторяющиеся случайные числа в numpy?

list = np.random.random_integers(20,size=(10))
Академия
источник
Что вы имеете в виду под «неповторяющимся»? Что последовательность случайных чисел никогда не повторяется? Это невозможно, поскольку состояние генератора случайных чисел должно соответствовать конечной памяти компьютера. Или вы имеете в виду, что ни одно число не встречается дважды?
Sven Marnach
5
Неповторяемость означает, что у вас есть список без дубликатов.
Polynomial
2
Возможно, вам нужна случайная перестановка? docs.scipy.org/doc/numpy/reference/generated/…
киборг,

Ответы:

106

numpy.random.Generator.choiceпредлагает replaceаргумент к образцу без замены:

from numpy.random import default_rng

rng = default_rng()
numbers = rng.choice(20, size=10, replace=False)

Если вы используете NumPy до 1.17, без GeneratorAPI, вы можете использовать random.sample()из стандартной библиотеки:

print(random.sample(range(20), 10))

Вы также можете использовать numpy.random.shuffle()и нарезку, но это будет менее эффективно:

a = numpy.arange(20)
numpy.random.shuffle(a)
print a[:10]

В replaceунаследованной numpy.random.choiceфункции также есть аргумент , но этот аргумент был реализован неэффективно, а затем оставлен неэффективным из-за гарантий стабильности потока случайных чисел, поэтому его использование не рекомендуется. (Он в основном выполняет функцию перемешивания и нарезки внутри.)

Свен Марнах
источник
1
print random.sample (range (20), 10) не работает с python 2.6 ?!
Academia
А ты import random?
Sven Marnach
Проблема возникла из-за неправильной конфигурации Pydev. Спасибо
Academia
1
Что, если у меня n не 20, а как 1000000, но мне нужно от него только 10 уникальных чисел, есть ли более эффективный подход к памяти?
mrgloom 08
2
@mrgloom В Python 3 random.sample(range(n), 10))будет эффективен даже для очень больших n, поскольку rangeобъект - это просто небольшая оболочка, хранящая значения начала, остановки и шага, но не создающая полный список целых чисел. В Python 2 вы можете заменить rangeна, xrangeчтобы получить аналогичное поведение.
Sven Marnach 09
108

Думаю, numpy.random.sampleсейчас не работает. Это мой путь:

import numpy as np
np.random.choice(range(20), 10, replace=False)
Стрнам
источник
25
Вместо range(n)(или arange(n)) в качестве первого аргумента choiceэквивалентно просто передать n, например choice(20, 10, replace=False).
Джош Боде
1
Обратите внимание, что np.random.choice(a, size, replace=False)это очень медленно для больших a- на моей машине около 30 мс для a = 1M.
Matthew Rahtz
3
Чтобы избежать проблем со временем и памятью при очень большом nиспользовании numpy.random.Generator.choice(начиная с numpy v1.17)
benbo
1
Главный недостаток, который я вижу, заключается в том, что np.random.choice не имеет параметра оси -> это только для 1d массивов.
Moosefeather
3

Спустя некоторое время для выбора 40000 из 10000 ^ 2 (Numpy 1.8.1, imac 2.7 ГГц):

import random
import numpy as np

n = 10000
k = 4
np.random.seed( 0 )

%timeit np.random.choice( n**2, k * n, replace=True )  # 536 µs ± 1.58 µs
%timeit np.random.choice( n**2, k * n, replace=False ) # 6.1 s ± 9.91 ms

# https://docs.scipy.org/doc/numpy/reference/random/index.html
randomstate = np.random.default_rng( 0 )
%timeit randomstate.choice( n**2, k * n, replace=False, shuffle=False )  # 766 µs ± 2.18 µs
%timeit randomstate.choice( n**2, k * n, replace=False, shuffle=True )   # 1.05 ms ± 1.41 µs

%timeit random.sample( range( n**2 ), k * n )          # 47.3 ms ± 134 µs

(Почему выбирают 40000 из 10000 ^ 2? Для создания больших scipy.sparse.random матриц - scipy 1.4.1 использует np.random.choice( replace=False ), slooooow.)

Совет перед множеством случайных людей.

Денис
источник
1

Вы также можете получить это, отсортировав:

random_numbers = np.random.random([num_samples, max_int])
samples = np.argsort(random_numbers, axis=1)
Бен
источник
-3

Просто сгенерируйте массив, содержащий требуемый диапазон чисел, затем перемешайте их, многократно меняя местами случайное число с 0-м элементом в массиве. Это создает случайную последовательность, не содержащую повторяющихся значений.

Полиномиальный
источник
2
Еще одно свойство полученной случайной последовательности состоит в том, что она не является особенно случайной .
Sven Marnach
@SvenMarnach - Однако для большинства целей он достаточно случайный. Он мог бы использовать подход с двойной случайностью, если бы хотел, чтобы он был более случайным.
Polynomial
Это бессмысленно. OP может использовать библиотечные вызовы, чтобы сделать это правильно. Они проще в использовании, работают быстрее и более читабельны, чем пользовательская версия. Я не могу придумать ни одной причины, по которой я должен использовать здесь неправильный алгоритм только потому, что он, вероятно, «достаточно случайный», когда использование правильного алгоритма не имеет никаких недостатков.
Sven Marnach
@SvenMarnach - Достаточно честно. Я не знаю numpy, поэтому я просто предлагал потенциальное решение.
Polynomial