Генерировать буквенно-цифровые случайные числа в numpy

Мне нужны случайные числа 100000+, я обнаружил, что numpy подходит для моего проекта, основываясь на производительности, это хорошо. Но я хочу 4-местное случайное число на основе приведенного ниже шаблона,

'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'

В приведенном выше случае 26 строчных букв, 26 заглавных букв и 10 цифр равны 62 буквам, и давайте возьмем перестановки и комбинации,

Я хочу 4 цифры из этих букв, так что,

62 ^ 4 / 4! = 615680 (Combinations)

Если я возьму 26 строчных букв + 10 цифр и выведу,

(26+10) ^ 4 / 4! = 69984 (Combinations)

Из этих двух случаев лучше всего подходит первый, он обеспечивает лучшие случайные числа, здесь я провел некоторую логику,

from numpy.random.mtrand import RandomState
import binascii
lo = 1000000000000000
hi = 999999999999999999
In [65]: %timeit [ binascii.b2a_hex(rand.randint(lo, hi, 2).tostring())[:4] for _ in xrange(100000)]
1 loops, best of 3: 272 ms per loop

Но подсчет случайных чисел ниже 100000, потому что он принимает только маленькие буквы + цифры

In [66]: len(set([binascii.b2a_hex(rand.randint(lo, hi, 2).tostring())[:4] for _ in xrange(100000)]))
Out[66]: 51210

Кто-нибудь предложит мне, как реализовать это в numpy?


person dhana    schedule 18.09.2014    source источник
comment
numpy.random.choice() 4-вектора из алфавита, а потом ''.join() каждого?   -  person NPE    schedule 19.09.2014
comment
Или, если бы вы рассказали нам о реальной проблеме, которую пытаетесь решить, мы могли бы лучше помочь вам.   -  person NPE    schedule 19.09.2014
comment
@NPE спасибо за ответ, я пытаюсь генерировать случайные числа 100000 каждый раз. Поэтому мне нужно сохранить каждое уникальное случайное число в nosql db. И в чем проблема, я хочу 4 места случайного числа. 62 буквы дают больше уникальных случайных чисел по сравнению с 36 буквами. Итак, исходя из приведенной выше логики, требуется 32 буквы, а не 64 буквы.   -  person dhana    schedule 19.09.2014
comment
Обычно люди используют для этого базу 64, то есть ваш алфавит и символы «+» и «/». Это делает все проще, так как теперь вы просто генерируете случайное число, а затем выполняете преобразование с основанием 64.   -  person Clarus    schedule 19.09.2014
comment
@Кларис, возможно, вы можете опубликовать свой комментарий в качестве ответа ...   -  person Saullo G. P. Castro    schedule 20.09.2014


Ответы (4)


Как указывает NPE, вы можете использовать numpy.random.choice. Этот код достигает того, что вы хотите?

import numpy as np

LENGTH = 4
NO_CODES = 100000

alphabet = list('abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789')
np_alphabet = np.array(alphabet, dtype="|S1")
np_codes = np.random.choice(np_alphabet, [NO_CODES, LENGTH])
codes = ["".join(np_codes[i]) for i in range(len(np_codes))]

print(codes)

Выполнение с NO_CODES = 1000000 занимает пару секунд на моем 2-летнем, но неплохом компьютере.

person marcotama    schedule 22.09.2014
comment
Запуск этого на python 3.5 дает мне сообщение об ошибке sequence item 0: expected str instance, numpy.bytes_ found - person NeStack; 20.03.2019
comment
Попробуйте изменить dtype на dtype="|U1" - person xyzzyqed; 18.11.2019

Это можно сделать намного быстрее, используя numpy view.

A, Z = np.array(["A","Z"]).view("int32") 

NO_CODES = 100
LEN = 20

np.random.randint(low=A,high=Z,size=NO_CODES*LEN,dtype="int32").view(f"U{LEN}")
person Ales Novak    schedule 18.11.2019

Принятый ответ можно сделать немного быстрее с помощью следующего кода:

import numpy as np

length  = 4
n_codes = 100000
alpha_num = list('abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789')

np_codes = np.random.choice(alpha_num, size=[n_codes, length])
codes = [code.tostring() for code in np_codes]

Исходная среда выполнения на моей машине: 10 loops, best of 3: 204 ms per loop.

Новая среда выполнения: 10 loops, best of 3: 27.6 ms per loop.

person Francois    schedule 15.08.2018

Ни один из двух других ответов не работал у меня, но я смог использовать их для создания следующего решения:

import numpy as np

length  = 4
n_codes = 100000
alpha_num = list('abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789')

np_codes = np.random.choice(alpha_num, size=[n_codes, length])
codes = [''.join(code) for code in np_codes]
person mgoldwasser    schedule 11.09.2019